Вопрос-ответ

MySQLSyntaxErrorException near "?" when trying to execute PreparedStatement

Исключение MySQLSyntaxErrorException рядом с "?" при попытке выполнить PreparedStatement

Я пытаюсь выполнить запрос, используя PreparedStatement в Java.

Я получаю ошибку под номером 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, на предмет правильного синтаксиса для использования рядом с '? или MemberName = ?' в строке 1


Переведено автоматически
Ответ 1

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 closing Connection, Statement и ResultSet в finally блоке try блока, в котором они были получены. Ознакомьтесь с базовым руководством по JDBC для получения более подробной информации.

Ответ 2

Если вы посмотрите на javadocs для Statement (суперкласс PreparedStatement), документы метода для executeQuery(String) и executeUpdate(String) говорят следующее:


Примечание: Этот метод нельзя вызвать с помощью PreparedStatement или CallableStatement.


Вот что вы здесь делаете: вызываете executeQuery(String) из Statement для PreparedStatement объекта.

Теперь, поскольку javadocs говорят, что вы "не можете" этого сделать, фактическое поведение, которое вы получаете, не определено ... и, вероятно, зависит от драйвера JDBC. В этом случае кажется, что используемый вами драйвер MySQL интерпретирует это как означающее, что вы выполняете обновление как неподготовленный оператор, так что ? токены НЕ интерпретируются как заполнитель параметра. Это приводит к тому, что серверный анализатор SQL выдает сообщение "синтаксическая ошибка".

(Программистам было бы проще, если бы драйвер MySQL выдавал другое непроверенное исключение, если бы вы сделали это; например UnsupportedOperationException. Однако стандартные javadocs JDBC не говорят, что должно произойти в этой ситуации. То, что будут делать их драйверы, зависит от поставщика.)

java mysql jdbc