如果欄位值可能為空,那么從表里面讀取資料的時候程式使用的變數型別應該使用 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
《SOD框架“企業級”應用資料架構實戰》
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/311930.html
標籤:其他
