Golang查询SQL中sql.NullTime值时遇MySQL语法错误求助
问题分析
你的报错核心原因是直接将Go的time.Time对象拼入SQL语句,导致生成的SQL中时间值既没有用单引号包裹,还包含MySQL无法识别的+0000 UTC后缀,触发语法错误。另外你代码里先格式化时间再解析的操作完全多余,属于冗余步骤。
解决方案
方案1:使用参数化查询(强烈推荐,避免SQL注入)
不要用fmt.Sprintf拼接SQL,改用数据库驱动支持的参数占位符(MySQL一般用?),让驱动自动处理时间类型的转换:
prevTime := time.Now().UTC().Add(-15 * time.Minute) currTime := time.Now().UTC() query := ` SELECT * FROM %s WHERE updated_on_utc > ? AND updated_on_utc <= ? ` // 先替换表名(表名不能用参数占位符) query = fmt.Sprintf(query, TableName) // 用参数化方式执行查询 rows, err := db.DbClient.Query(query, prevTime, currTime) // 后续处理rows和err...
方案2:手动格式化时间并拼入SQL(不推荐,有注入风险)
如果你一定要拼接SQL,需要把时间格式化为MySQL支持的字符串(比如2006-01-02 15:04:05),并且用单引号包裹:
layout := "2006-01-02 15:04:05" prevTime := time.Now().UTC().Add(-15 * time.Minute).Format(layout) currTime := time.Now().UTC().Format(layout) query := ` SELECT * FROM %s WHERE updated_on_utc > '%s' AND updated_on_utc <= '%s' ` query = fmt.Sprintf(query, TableName, prevTime, currTime) data := db.DbClient.ExecuteQuery(query)
关键注意点
- 永远优先用参数化查询,这是防止SQL注入的核心手段,同时避免类型转换错误。
- 表名无法用参数占位符,所以可以用
fmt.Sprintf替换,但要确保表名是安全的(比如来自常量,不是用户输入)。 - Go的
time.Time对象可以直接通过参数化查询传递给MySQL驱动,驱动会自动转换成数据库兼容的格式。
内容的提问来源于stack exchange,提问作者Siddhant Sinha
相关产品推荐
相关产品推荐

