GO語言程序查詢數據庫字段為空遇到的幾個問題總結


如果字段值可能為空,那么從表里面讀取數據的時候程序使用的變量類型應該使用 sql.NullXXX 類型,比如下面的日期類型:

var id uint
var createAt time.Time
var updateAt time.Time
var deleteAt sql.NullTime
var name string
var gartenId uint
var beginAt time.Time
var endAt time.Time
var monthBegin int
var monthEnd int
var child []byte
var content []byte
var creator uint

 開始的時候,deleteAt 使用的也是 time.Time類型。

err = rows.Scan(&id,
			&createAt,
			&updateAt,
			&deleteAt,
			&name,
			&gartenId,
			&beginAt,
			&endAt,
			&monthBegin,
			&monthEnd,
			&child,
			&content,
			&creator)

 這里讀取數據都沒有問題,但是發現當數據庫日期類型字段為NULL的時候,日期類型變量讀取到的是0000年的默認日期值,如果稍后再用這個默認值插入數據庫,會出現下面的錯誤:

incorrect datetime value: ‘0000-00-00‘ for column ‘start‘ at row 1

要解決這個問題的辦法,就不能使用日期類型變量的默認值插入數據庫,可以定義一個引用類型的變量,比如下面的代碼,在上面Scan之后將讀取出來的變量值賦值給一個結構對象。當然前提得定義變量為sql.NullXXX類型,比如下面代碼中的 deleteAt變量:

var recipe entity.RecipeDO

recipe.ID = &id
recipe.CreateAt = &createAt
recipe.UpdateAt = &updateAt
if deleteAt.Valid {
	recipe.DeleteAt = &deleteAt.Time
}
recipe.Name = &name

 這樣如果數據庫字段值為空的話,deleteAt.Valid為假,那么 recipe.DeleteAt 字段就是空了(nil),下面看下 RecipeDO 結構體的定義:

type RecipeDO struct {
	ID         *uint             
	CreateAt   *time.Time       
	UpdateAt   *time.Time        
	DeleteAt   *time.Time        
	Name       *string           
	GartenID   *uint             
	BeginAt    *time.Time        
	EndAt      *time.Time         
	MonthBegin *int               
	MonthEnd   *int              
	ChildList  *[]*ChildForRecipe 
	Content    *[]*DailyMenu     
	Creator    *uint              
}

 以后插入數據的時候,判斷下結構體字段 DeleteAt是否為空,寫不同的插入代碼即可,如下示例:

        if do.DeleteAt != nil {
		_, err = stmt.Exec(*do.UpdateAt, *do.DeleteAt, *do.Name, *do.GartenID, *do.BeginAt, *do.EndAt, *do.MonthBegin, *do.MonthEnd, jsChildList, jsContent, *do.ID)
	}else{
		_, err = stmt.Exec(*do.UpdateAt, nil, *do.Name, *do.GartenID, *do.BeginAt, *do.EndAt, *do.MonthBegin, *do.MonthEnd, jsChildList, jsContent, *do.ID)
	}

 當然也可以在上面的代碼中Exec方法的第二個參數定義一個 sql.NullTime類型,就不用寫上面的分支代碼了。

PS:

GO語言程序查詢數據處理空值的方式還是比較簡陋的,容易掉坑里面去。要避免這個問題,最簡單的辦法還是在建表的時候,給所有字段都設置默認值。當然有時候字段值為NULL有特殊業務含義的話,上面的解決過程是繞不開了。

彩蛋:

上面示例中 RecipeDO 結構體的Content字段是一個復雜結構,數據庫對應的表的Content字段是一個json類型,這個字段插入數據庫之前必須先Json序列化,補上序列化它們的代碼:

        jsContent,err1 :=json.Marshal(*do.Content)
	if err1 != nil {
		logger.Errorf("Recipe update Content to JSON ", query, err1.Error())
		return  err1
	}

 同樣,從數據庫讀取這個字段,也要反序列化處理一下:

		err = rows.Scan(&id,
			&createAt,
			&updateAt,
			&deleteAt,
			&name,
			&gartenId,
			&beginAt,
			&endAt,
			&monthBegin,
			&monthEnd,
			&child,
			&content,
			&creator)
//其余代碼略
var recipe entity.RecipeDO
//其余代碼略

//反序列化content字段讀取的值
var contentObj = make([]*entity.DailyMenu, 0)
		err = json.Unmarshal(content, &contentObj)
		if err != nil {
			logger.Errorf(" GetDO parse content error, ", query, err.Error())
			return nil, err
		}
		recipe.Content = &contentObj

 

參考鏈接:

go mysql null_Go 查詢數據庫 Scan Null 字段報錯解決辦法

https://blog.csdn.net/weixin_30940057/article/details/113566387?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.no_search_link&spm=1001.2101.3001.4242

go語言scan空值報錯

https://blog.csdn.net/leonpengweicn/article/details/51192557

解決Go語言數據庫中null值的問題

https://www.jb51.net/article/202690.htm

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM