You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 06:20:01