PreparedStatement: отсутствует выражение в одинарных кавычках (ORA-00936) - PullRequest
0 голосов
/ 03 октября 2018

Я запрашиваю базу данных Oracle следующим образом:

try (Connection c = dataSource.getConnection();
    PreparedStatement p = c.prepareStatement(
        "SELECT * FROM table WHERE column_string = ?")) {
    p.setString(1, input);

    try (ResultSet r = p.executeQuery()) {
        // handle ResultSet
    }
}

И строка input получена от пользователя.Этот вызов работает для обычных входных строк, например:

hello world
special: characters 0_2 (ftlo) -

Но не удается выполнить ввод для такой строки:

7-8 l/o y-S '

(обратите внимание на тире, косую черту и одинарные кавычки вконец)

Я предполагал, что это связано с одинарной кавычкой, но у меня сложилось впечатление, что PreparedStatement позаботится обо всем побеге для вас.Кто-нибудь видел подобные проблемы или знает больше о побеге символов в драйверах JDBC oracle?

Я использую:

  • Java: 1.8.0_181
  • Jboss: EAP 6.4.7.GA
  • JDBC: ojdbc6 версия 11.2.0.3.0
  • База данных: Oracle Database 11g Enterprise Edition, выпуск 11.2.0.4.0 - 64-разрядная версия

Stacktrace:

SQLSyntaxErrorException: ORA-00936: missing expression
oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445)
oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879)
oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450)
oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207)
oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:884)
oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1167)
oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1289)
oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3584)
oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3628)
oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1493)
org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:462)
... <my classes>

Ответы [ 3 ]

0 голосов
/ 03 октября 2018

Невозможно воспроизвести.Добавлен файл ojdbc6-11.2.0.3.jar из здесь .

Ран после MCVE код для сервера 12.1.0.2 (значения для getConnection, конечно, были замаскированы).

public static void main(String[] args) throws Exception {
    test("hello world");
    test("special: characters 0_2 (ftlo) -");
    test("7-8 l/o y-S '");
    test("X");
}
private static void test(String input) throws SQLException {
    System.out.println(input);
    try (Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@XXX:1521:XXX", "XXX", "XXX")) {
        String sql = "select DUMMY from DUAL where DUMMY = ?";
        try (PreparedStatement stmt = conn.prepareStatement(sql)) {
            stmt.setString(1, input);
            try (ResultSet rs = stmt.executeQuery()) {
                int count = 0;
                while (rs.next()) {
                    System.out.println("  " + rs.getString("DUMMY"));
                    count++;
                }
                System.out.println("  " + count + " rows");
            }
        }
    }
}

Выход

hello world
  0 rows
special: characters 0_2 (ftlo) -
  0 rows
7-8 l/o y-S '
  0 rows
X
  X
  1 rows
0 голосов
/ 04 октября 2018

На самом деле оказалось, что я получаю сообщение об ошибке, отличное от того, что я думал.Мой ResultSetHandler выполняет некоторую дополнительную логику очистки после завершения основного запроса, и это вызывает исключение SQLException (отсутствует выражение).Из-за реализации библиотек apache DButils и JDBC ошибка была проглочена и не была напечатана полезным способом.Извините за путаницу.

0 голосов
/ 03 октября 2018

Возможно, проблема связана с одинарной кавычкой, потому что в Oracle последняя должна повторяться дважды, чтобы быть интерпретированной как одинарная кавычка, или целая строка должна быть включена в конструкцию q '{...}', где ... - данная строка.

...