前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >GO语言程序查询数据库字段为空遇到的几个问题总结

GO语言程序查询数据库字段为空遇到的几个问题总结

作者头像
用户1177503
发布2021-11-30 17:10:08
3.2K0
发布2021-11-30 17:10:08
举报
文章被收录于专栏:程序员的SOD蜜程序员的SOD蜜

如果字段值可能为空,那么从表里面读取数据的时候程序使用的变量类型应该使用 sql.NullXXX 类型,比如下面的日期类型:

代码语言:javascript
复制
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类型。

代码语言:javascript
复制
err = rows.Scan(&id,
			&createAt,
			&updateAt,
			&deleteAt,
			&name,
			&gartenId,
			&beginAt,
			&endAt,
			&monthBegin,
			&monthEnd,
			&child,
			&content,
			&creator)

这里读取数据都没有问题,但是发现当数据库日期类型字段为NULL的时候,日期类型变量读取到的是0000年的默认日期值,如果稍后再用这个默认值插入数据库,会出现下面的错误:

代码语言:javascript
复制
incorrect datetime value: ‘0000-00-00‘ for column ‘start‘ at row 1

要解决这个问题的办法,就不能使用日期类型变量的默认值插入数据库,可以定义一个引用类型的变量,比如下面的代码,在上面Scan之后将读取出来的变量值赋值给一个结构对象。当然前提得定义变量为sql.NullXXX类型,比如下面代码中的 deleteAt变量:

代码语言:javascript
复制
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 结构体的定义:

代码语言:javascript
复制
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是否为空,写不同的插入代码即可,如下示例:

代码语言:javascript
复制
        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序列化,补上序列化它们的代码:

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

同样,从数据库读取这个字段,也要反序列化处理一下:

代码语言:javascript
复制
		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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-10-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • go mysql null_Go 查询数据库 Scan Null 字段报错解决办法
  • go语言scan空值报错
  • 解决Go语言数据库中null值的问题
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档