我正在尝试在golang中完成一个简单的许可系统,并尝试了许多方法来使其工作。基本上,我已经在我的数据库中输入了几个随机许可密钥,我的golang程序应检查用户输入密钥是否存在,如果存在,则将用户指定的用户名和密码添加到数据库中以便以后登录。
这是我没有工作过的代码:
"IF EXISTS (SELECT * FROM login WHERE LK = "+reglicenceEntry.Text()+") THEN
INSERT INTO `login` (`Username`, `Password`, `LK`) VALUES
('"+regusernameEntry.Text()+"', '"+regpasswordEntry.Text()+"', ''); "
这是golang错误:
错误1064:您的SQL语法出错;查看与您的MySQL服务器版本相对应的手册,以便在#< IF EXISTS附近使用正确的语法(SELECT * FROM login WHERE LK =' 5qp515YHXEmSDzwqgoJh')然后插入'在第1行
非常感谢!
答案 0 :(得分:1)
MySQL语法不支持IF...THEN
构造,除了存储的例程和触发器和事件。见https://dev.mysql.com/doc/refman/8.0/en/sql-syntax-compound-statements.html
我建议为您的代码提供替代解决方案:
INSERT INTO `login` (`Username`, `Password`, `LK`)
SELECT ?, ?, ''
FROM `login`
WHERE `LK` = ?
LIMIT 1
如果您的登录表没有LK值,则上面的SELECT将返回0行,因此不会插入任何内容。
如果您的登录表具有LK值,则上面的SELECT将返回至少1行(并且我将其限制为1),因此它将插入一行。它插入的行包含您的用户名和密码,以及LK的空白字符串。
我展示了参数占位符的使用。您应该在SQL中使用参数,而不是将变量连接到查询中。这是避免意外SQL注入的好习惯。有关示例,请参阅http://go-database-sql.org/prepared.html。
使用参数的目的是避免SQL注入问题。有关SQL注入的说明,请参阅我对What is SQL injection?的回答。
或我的演示文稿SQL Injection Myths and Fallacies(或youtube video)。
使用参数时,您需要执行两个步骤。
?
)准备查询的第一步,否则您将把变量连接到SQL查询中。 关键是要将变量与查询分开,因此如果变量中有任何内容可能会无意中更改您的SQL语法(如不平衡引号),则它永远不会与SQL结合使用。在进行准备之后,MySQL已经被MySQL服务器解析了,之后就没有办法改变语法了。
MySQL记得需要填写查询的哪些部分,当你在执行步骤中传递变量时,MySQL会使用你的值填充查询的缺失部分 - 但这发生在MySQL服务器内,而不是在你的服务器中应用。因此,查询的动态部分 - 您的变量 - 与SQL语法分开,避免了SQL注入问题。
对于你的问题中描述的任务,它看起来像这样(我没有测试过这个Go代码,但它应该让你走上正确的道路)。
stmt, err := tx.Prepare("INSERT INTO `login` (`Username`, `Password`, `LK`) SELECT ?, ?, '' FROM `login` WHERE `LK` = ? LIMIT 1")
if err != nil {
log.Fatal(err)
}
defer stmt.Close()
_, err = stmt.Exec(regusernameEntry.Text(), regpasswordEntry.Text(), reglicenceEntry.Text())
if err != nil {
log.Fatal(err)
}
参数的顺序很重要。传递给Exec()
的变量必须与?
占位符在准备好的SQL语句中出现的顺序相同。它们由MySQL服务器以相同的顺序一对一地匹配。
不要在准备好的SQL语句中的占位符周围加引号。这将在SQL中作为文字字符串'?'
。对占位符使用不带引号的?
字符。当它在服务器中由MySQL组合时,它就像你在字符串周围放置引号一样 - 但是即使包含特殊字符的字符串值也没有SQL注入的风险。
这是另一个提供更多代码示例的网站:https://github.com/go-sql-driver/mysql/wiki/Examples
Exec()
函数用于执行没有结果集的SQL,如INSERT,UPDATE,DELETE。 Go SQL驱动程序中还有其他函数,如Query()
和QueryRow()
,它们也接受参数参数。如果SQL返回结果集,则使用这些。