预准备语句中的 MYSQL 异常在 '?' 附近使用正确的语法

标签 mysql jdbc

我编写了以下代码。但我收到 MySQL 异常,要求在“?”附近使用正确的语法。 你能帮我解决这个问题吗?

public static void inbox(String username) {
    String query_recipient = "SELECT user_id, first_name, last_name FROM user_info WHERE username = '" + username + "' ";
    String query = "SELECT sub, msg FROM message WHERE recipient = ?";
    Statement s = null;
    PreparedStatement ps = null;
    ResultSet rs = null;
    ResultSet rs1 = null;
    int userId = 0;

    try {
        s = Connect.con.createStatement();
        rs = s.executeQuery(query_recipient);
        rs.next();
        userId = rs.getInt("user_id");

        ps = Connect.con.prepareStatement(query);
        ps.setInt(1, userId);

        rs1 = ps.executeQuery(query);

        while (rs1.next()) {
            System.out.println(rs1.getString("sub"));
            System.out.println(rs1.getString("msg"));
        }

    } catch (SQLException ex) {
        Logger.getLogger(UserBAL.class.getName()).log(Level.SEVERE, null, ex);
    } //end catch
} //end inbox()

编辑:这是错误消息

SEVERE: null
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 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 '?' at line 1
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1053)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4120)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4052)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2503)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2664)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2788)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2738)
at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1617)
at msg_pkg.MsgBAL.inbox(MsgBAL.java:82)
at msg_pkg.MsgBAL.main(MsgBAL.java:116)

最佳答案

我在您的代码中发现了一些错误:

  1. 您正在将 SQL 语句传递给准备好的语句...这不仅没有必要,而且是错误的。检查the documentation for the executeQuery() method of prepared statements.
  2. 检索用户结果集后,只需移至下一行...这可能有效,但正确的方法是:转到结果集的第一行(使用rs.first())。

    同样的事情发生在下面的几行中:您移动到消息结果集的下一行;您应该首先移动到第一行之前,然后移动到下一行(当有下一行时)。

  3. (个人建议)第一个查询容易受到SQL injection attacks的影响。既然您已经在使用准备好的语句,为什么不使用准备好的语句来获取用户 ID?
  4. (个人建议),我认为最好使用 try with resources ,而不是使用 try ... catch 风格(这并没有错)。风格。这样,您就可以在程序完成资源(在本例中为准备好的语句)后强制关闭它们。

让我们稍微清理一下您的代码:

public static void inbox(String username) {
    /* 
       First: Avoid SQL injection risks: use a prepared statement 
       to get user data.
    */
    String qryRec = "SELECT user_id, first_name, last_name "
                  + "FROM user_info "
                  + "WHERE username = ?";
    String qryMsg = "SELECT sub, msg "
                  + "FROM message "
                  + "WHERE recipient = ?";
    ResultSet rsRec = null, 
              rsMsg = null;

    // "try-with-resources"
    try(
        PreparedStatement psRec = Connect.con.prepareStatement(qryRec);
        PreparedStatement psMsg = Connect.con.prepareStatement(qryMsg);
    ) {
        // Set the parameter for psRecipient, and execute the query
        psRec.setString(1, username);
        rsRec = psRec.executeQuery(); // No need to pass the query 
                                      // as an argument here; it's
                                      // already prepared

        // Go to the first row of rsRecipient
        rsRec.first();

        // Set the parameter for psMessage, and execute the query
        psMsg.setInt(1, rsRecipient.getInt("user_id");
        rsMsg = psMmsg.executeQuery(); // No need to pass the query 
                                       // as an argument here; it's
                                       // already prepared

        // Go to the resultset "header" (i.e. before the first row
        rsMsg.beforeFirst();
        while(rsMsg.next()) {
            System.out.println(rsMsg.getString("sub"));
            System.out.println(rsMsg.getString("msg"));
        }

        // Remember to close the result sets
        try {
            if(rsRec != null)
                rsRec.close();
        } catch(SQLException e) {/*Ignore*/} finally {rsRec = null;}

        try {
            if(rsMsg != null)
                rsMsg.close();
        } catch(SQLException e) {/*Ignore*/} finally {rsMsg = null;}
    } catch(SQLException e) {
        // Handle exception
    }
}

希望这有帮助

关于预准备语句中的 MYSQL 异常在 '?' 附近使用正确的语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30038718/

相关文章:

mysql - MySQL 中的 OR 与 AND

php - php中db(sql)数据的数值检查和操作不起作用

mysql - 从 MySQL 存储过程执行 shell 命令

java - 无法从 Web 应用程序通过 JDBC 连接到 HIVE

java - 如何在Mysql数据库中插入jcombobox值

mysql - Rails 3 - 存储 float 的问题

MySQL 查询调优 - 为什么使用变量中的值比使用文字慢得多?

hadoop - Sqoop 从 SybaseIQ 导入到 Hive - java.io.IOException : SQLException in nextKeyValue

Java ResultSet.getString() 用于日期字段显示 00 :00:00. 0

mysql - Mysql默认的服务器端取数是多少