如何避免SQL插入操作时自动添加单引号?
问题解决方法
你遇到的问题是因为Go标准库的database/sql参数化查询会自动给字符串参数添加单引号,而ClickHouse的FORMAT JSONEachRow要求纯JSON结构,单引号会破坏JSON语法,导致插入失败。下面是几种可行的解决办法:
方法一:直接构造合法的JSON行字符串
如果event是可信的(比如是程序自身生成的JSON,无用户输入风险),可以用fmt.Sprintf拼接出符合要求的JSON行:
import "fmt" // %q会自动转义字符串中的特殊字符,生成合法的JSON字符串值 jsonRow := fmt.Sprintf(`{"event_raw": %q}`, event) query := `INSERT INTO logs FORMAT JSONEachRow ` + jsonRow _, err := s.db.ExecContext(ctx, query)
这样生成的SQL语句就是INSERT INTO logs FORMAT JSONEachRow {"event_raw": "{\"id\":\"abcdefgh\"}"},完全符合ClickHouse的要求。
方法二:使用普通VALUES插入(更推荐)
放弃FORMAT JSONEachRow,改用标准的INSERT VALUES语法,让驱动自动处理参数:
query := `INSERT INTO logs (event_raw) VALUES (?)` _, err := s.db.ExecContext(ctx, query, event)
这是参数化查询的标准用法,既安全(可防止SQL注入),又无需手动处理JSON格式,驱动会自动将event字符串作为event_raw字段的值插入数据库。
方法三:将整个JSON行作为参数传入(依赖驱动支持)
部分ClickHouse的Go驱动支持将完整JSON行作为参数传入,可尝试这种写法:
jsonRow := fmt.Sprintf(`{"event_raw": %q}`, event) query := `INSERT INTO logs FORMAT JSONEachRow ?` _, err := s.db.ExecContext(ctx, query, jsonRow)
注意这种方式依赖驱动实现,通用性不如前两种。
提示:如果
event包含用户输入内容,务必避免直接拼接SQL(方法一的风险点),优先使用方法二的参数化查询,防范SQL注入攻击。
内容的提问来源于stack exchange,提问作者Ado Ren
相关产品推荐
相关产品推荐

