doutong1890 2018-05-06 17:37
浏览 110
已采纳

如果表中存在许可密钥,则MySQL代码可将用户名和密码插入表中

I am trying to accomplish a simple licensing system in golang and have tried numerous ways to get it to work. Basically, I have input a couple of random licensing keys into my database and my golang program should check to see if the user-input key exists and if it does then add the user specified username and password into the database to login later.

This is the code that I have that hasn't been working:

"IF EXISTS (SELECT * FROM login WHERE LK = "+reglicenceEntry.Text()+") THEN 
 INSERT INTO `login` (`Username`, `Password`, `LK`) VALUES 
 ('"+regusernameEntry.Text()+"', '"+regpasswordEntry.Text()+"', ''); "

This is the golang error:

Error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF EXISTS (SELECT * FROM login WHERE LK = '5qp515YHXEmSDzwqgoJh') THEN INSERT IN' at line 1

Thanks so much!

  • 写回答

1条回答 默认 最新

  • douqian4411 2018-05-06 18:11
    关注

    MySQL syntax doesn't support IF...THEN constructs except within stored routines and triggers and events. See https://dev.mysql.com/doc/refman/8.0/en/sql-syntax-compound-statements.html

    I suggest an alternative solution for your code:

    INSERT INTO `login` (`Username`, `Password`, `LK`)
    SELECT ?, ?, ''
    FROM `login`
    WHERE `LK` = ?
    LIMIT 1
    

    If your login table does not have the LK value, the SELECT above will return 0 rows, therefore it will not insert anything.

    If your login table has the LK value, the SELECT above will return at least 1 row (and I limit it to 1), therefore it will insert a row. The row it inserts is comprised of your username and password, and a blank string for the LK.

    I showed use of parameter placeholders. You should use parameters in SQL instead of concatenating variables into your query. This is good practice to avoid accidental SQL injection. See http://go-database-sql.org/prepared.html for examples.


    The purpose of using parameters is to avoid SQL injection problems. See my answer to What is SQL injection? for an explanation of SQL injection.

    Or my presentation SQL Injection Myths and Fallacies (or youtube video).

    When using parameters, you do two steps.

    • The first step to prepare a query with placeholders (?) where you would otherwise concatenate variables into your SQL query.
    • The second step is to execute the prepared query, and this is the time you pass the variables to fill in the placeholders.

    The point is to keep variables separate from your query, so if there's anything in the variable that could unintentionally change your SQL syntax (like imbalanced quotes), it is never combined with the SQL. After you do the prepare, the SQL has already been parsed by the MySQL server, and there's no way to change the syntax after that.

    MySQL remembers which parts of the query need to be filled in, and when you pass variables during the execute step, MySQL fills in the missing parts of the query using your values — but this happens within the MySQL server, not in your application.

    Thus the dynamic parts of the query — your variables — are kept separate from the SQL syntax and you avoid SQL injection problems.

    For your task described in your question, it would look something like this (I have not tested this Go code, but it should put you on the right path).

    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)
    }
    

    The order of parameters is important. The variables you pass to Exec() must be in the same order that the ? placeholders appear in your prepared SQL statement. They are matched up, one for one, in the same order, by the MySQL server.

    Do not put quotes around the placeholders in your prepared SQL statement. That will work as a literal string '?' in SQL. Use an unquoted ? character for a placeholder. When it gets combined by MySQL in the server, it will work as if you had put quotes around the value like a string — but with no risk of SQL injection even if that string value containing special characters.

    Here's another site that gives more code examples: https://github.com/go-sql-driver/mysql/wiki/Examples

    The Exec() function is for executing SQL that has no result set, like INSERT, UPDATE, DELETE. There are other functions in the Go SQL driver like Query() and QueryRow() that also accept parameter arguments. You'd use these if your SQL returns a result set.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 给自己本科IT专业毕业的妹m找个实习工作
  • ¥15 用友U8:向一个无法连接的网络尝试了一个套接字操作,如何解决?
  • ¥30 我的代码按理说完成了模型的搭建、训练、验证测试等工作(标签-网络|关键词-变化检测)
  • ¥50 mac mini外接显示器 画质字体模糊
  • ¥15 TLS1.2协议通信解密
  • ¥40 图书信息管理系统程序编写
  • ¥20 Qcustomplot缩小曲线形状问题
  • ¥15 企业资源规划ERP沙盘模拟
  • ¥15 树莓派控制机械臂传输命令报错,显示摄像头不存在
  • ¥15 前端echarts坐标轴问题