“?”附近的 MySQLSyntaxErrorException尝试执行 PreparedStatement 时

Posted

技术标签:

【中文标题】“?”附近的 MySQLSyntaxErrorException尝试执行 PreparedStatement 时【英文标题】:MySQLSyntaxErrorException near "?" when trying to execute PreparedStatement 【发布时间】:2011-05-07 01:49:37 【问题描述】:

我正在尝试使用 Java 中的 PreparedStatement 执行查询。

我在尝试执行查询时收到错误号 1064(语法错误)。

我已经在 mysql 查询浏览器中使用替代值对此进行了测试,效果很好。

我的代码有什么问题?

以下是相关代码:

String query = "select MemberID, MemberName from members where MemberID = ? or MemberName = ?";
Connection conn = DriverManager.getConnection(DATABASE_URL, USERNAME, PASSWORD);
PreparedStatement s = conn.prepareStatement(query);
s.setInt(1, 2);
s.setString(2, "zen");
ResultSet rs = s.executeQuery(query);

这是我得到的例外:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 你有一个 SQL 语法错误;检查与您对应的手册 MySQL 服务器版本,以便在 '? 附近使用正确的语法或会员名 = ?'在第 1 行

【问题讨论】:

提供有关“错误”的更多详细信息 - Java 中的异常具有堆栈跟踪 就在调用 executeQuery 之前,我在调试期间看到参数被替换到 PreparedStatemet 中,查询变为“com.mysql.jdbc.JDBC4PreparedStatement@6e9770a3: select MemberID, MemberName from members where MemberID = 2 或 MemberName = 'zen'" 好吧,你已经提供了你的全部代码。这就是没有人回答的原因——太长了。隔离相关位并仅显示它们。 【参考方案1】:

如果您查看 StatementPreparedStatement 的超类)的 javadocs,executeQuery(String)executeUpdate(String) 的方法文档会这样说:

注意:不能在 PreparedStatementCallableStatement 上调用此方法。

这就是你在这里所做的:在 PreparedStatement 对象上从 Statement 调用 executeQuery(String)

现在由于 javadocs 说你“不能”这样做,你得到的实际行为是未指定的......并且可能依赖于 JDBC 驱动程序。在这种情况下,您使用的 MySQL 驱动程序似乎将其解释为意味着您正在将更新作为非准备语句进行,因此? 标记不会被解释为参数占位符。这会导致服务器端 SQL 解析器说“语法错误”。

(如果您这样做,如果 MySQL 驱动程序抛出不同的未经检查的异常,程序员会更容易;例如 UnsupportedOperationException。但是,标准 JDBC javadocs 没有说明在这种情况下应该发生什么。它由供应商决定他们的驱动程序会做什么。)

【讨论】:

JDBC 规范确实说明了应该发生的情况:应该抛出 SQLException" SQLException - 如果发生数据库访问错误,则在关闭的语句上调用此方法,给定的 SQL语句生成除单个 ResultSet 对象之外的任何内容,在 PreparedStatement 或 CallableStatement 上调用该方法"。但是,MySQL 驱动程序只是在这种情况下“偶然”执行此操作(如果传递的语句没有参数占位符,它将与规范相反)。较旧的 JDBC 规范(IIRC JDBC 3 及更早版本)没有此要求。【参考方案2】:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以了解在 '? 附近使用的正确语法。或 MemberName = ?'在第 1 行

MySQL 不理解 SQL 查询中? 的含义。这确实是无效的 SQL 语法。所以不知何故它没有被PreparedStatement取代。你猜怎么着?

PreparedStatement s = conn.prepareStatement(query);
s.setInt(1, intValue);
s.setString(2, strValue);        
rs = s.executeQuery(query); // Fail!

您正在用原始查询覆盖准备好的查询!您需要调用无参数的PreparedStatement#executeQuery() 方法而不是Statement#executeQuery(String)

PreparedStatement s = conn.prepareStatement(query);
s.setInt(1, intValue);
s.setString(2, strValue);        
rs = s.executeQuery(); // OK!

与问题无关,您的代码正在泄漏资源。几个小时后数据库将用完它们,您的应用程序将崩溃。要解决此问题,您需要遵循 JDBC 习惯用法,在获取它们的 try 块的 finally 块中关闭 ConnectionStatementResultSet。查看JDBC basic tutorial了解更多详情。

【讨论】:

这只是一个家庭作业,而且我截断了我的大部分代码,我确实有一个关闭所有相关资源的方法。我试过 executeQuery() 它现在可以工作了,谢谢:P

以上是关于“?”附近的 MySQLSyntaxErrorException尝试执行 PreparedStatement 时的主要内容,如果未能解决你的问题,请参考以下文章

怎么查看自己附近的基站?

关键字 'if' 附近有语法错误。

附近的小程序知识盘点

如何仅获取路径节点的附近子集

加快附近组的计算?

微信怎么查看附近的小程序 微信查看附近的小程序的方法