Go语言使用db.Exec传递变量到MySQL创建表时出错
问题原因与解决方案
错误原因
Go的database/sql包及MySQL驱动中的?占位符仅用于替换SQL语句中的值参数(如INSERT、SELECT语句里的字段值),不能用来替换表名、列名这类SQL标识符。
当你尝试用?传递表名时,驱动会自动给参数加上单引号,最终生成的SQL语句会变成:
CREATE TABLE 'dokimi03' (id bigint(20) NOT NULL AUTO_INCREMENT, ...)
而MySQL的语法中,表名不需要用单引号包裹(特殊场景需用反引号),这就直接导致了语法错误。
解决方法
需要通过字符串拼接生成包含表名的SQL语句,但必须严格校验表名的合法性以避免SQL注入风险:
示例代码
import ( "fmt" "log" "strings" ) func main() { pinakas := "dokimi03" // 校验表名:仅允许字母、数字、下划线,可根据需求调整规则 validChars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" if strings.Trim(pinakas, validChars) != "" { log.Println("非法表名,仅允许字母、数字、下划线") return } // 拼接SQL语句,若表名含特殊字符/关键字,需用反引号包裹:`%s` crTable := fmt.Sprintf(`CREATE TABLE %s ( id bigint(20) NOT NULL AUTO_INCREMENT, username varchar(100) NOT NULL, password varchar(100) NOT NULL, email varchar(100) NOT NULL, PRIMARY KEY (id) );`, pinakas) _, errCreate := db.Exec(crTable) if errCreate != nil { log.Println(errCreate) } }
关键注意事项
- 若表名包含特殊字符或MySQL关键字,需用反引号包裹表名,比如
fmt.Sprintf("CREATE TABLE%s...", pinakas)。 - 绝对不能直接拼接未校验的用户输入作为表名,否则会引发严重的SQL注入漏洞。
内容的提问来源于stack exchange,提问作者Krackout
相关产品推荐
相关产品推荐

