使用Go的db.Exec执行MySQL GRANT语句时遇语法错误求助
解决Go中
database/sql执行GRANT语句的参数绑定问题 错误原因分析
- 第一种写法
GRANT USAGE ON *.* TO ?@? IDENTIFIED BY ?的问题:SQL语法中?@?不符合规范,@是账户标识的分隔符,这种占位符使用方式会让数据库无法正确解析,触发语法错误。 - 第二种写法把
?放在单引号里:驱动会将单引号包裹的?视为普通字符串,不会作为参数占位符,因此提示"预期0个参数,实际传入3个"的错误。
可行解决方案
方案一:用CONCAT函数拼接合法账户标识
通过MySQL的CONCAT函数生成符合语法要求的'username'@'host'格式,同时利用参数占位符避免SQL注入:
_, err = db.Exec("GRANT USAGE ON *.* TO CONCAT('''', ?, ''', ''@'', ''', ?, '''') IDENTIFIED BY ?", "test1", "%", "test1")
这里的''''是SQL中单引号的转义写法,用于在拼接结果中生成包裹用户名和主机名的单引号。
方案二:预先构建合法账户字符串(仅适用于可信参数)
如果参数是内部配置等完全可信的内容,可以直接拼接出符合要求的账户字符串,再作为参数传入:
// 构建 'test1'@'%' 格式的字符串 userAccount := fmt.Sprintf("'%s'@'%s'", "test1", "%") _, err = db.Exec("GRANT USAGE ON *.* TO ? IDENTIFIED BY ?", userAccount, "test1")
⚠️ 注意:此方式不能用于不可信的用户输入,否则会存在SQL注入风险。
推荐方案:遵循MySQL最新规范(分步骤操作)
从MySQL 5.7.6开始,GRANT语句中的IDENTIFIED BY子句已被废弃,推荐先创建用户再执行授权,这种方式也能避免参数绑定的语法问题:
// 第一步:创建用户 _, err = db.Exec("CREATE USER ? IDENTIFIED BY ?", "test1@%", "test1") if err != nil { fmt.Println(err) return } // 第二步:执行授权 _, err = db.Exec("GRANT USAGE ON *.* TO ?", "test1@%") if err != nil { fmt.Println(err) }
内容的提问来源于stack exchange,提问作者Vivek
相关产品推荐
相关产品推荐

