2014-10-22 2 views
7

Я хотел бы создать JDBC PreparedStatement, как:Как избежать буквального знак вопроса («?») В JDBC подготовил заявление

SELECT URL,LOCATE ('?', URL) pos FROM Links WHERE pageId=? ORDER BY pos ASC 

Если первый ? является буквальным и второй ? является параметром. Я мог бы использовать CHAR(63) вместо '?', но я думаю, что дополнительный вызов функции замедлит выполнение SQL. Есть ли способ избежать этого первого ??

Edit:

утверждение Следующий код пробы Популярность dkatzel о том, что ? символ в строке не считается маркером:

public class Test { 
    public static void main(String[] args) throws SQLException { 
     Connection conn = DriverManager.getConnection("jdbc:h2:mem:test"); 
     Statement stmt = conn.createStatement(); 
     stmt.executeUpdate("CREATE TABLE Links(URL VARCHAR(255) PRIMARY KEY,pageId BIGINT)"); 
     stmt.executeUpdate("INSERT INTO Links(URL,pageId) VALUES('http://foo.bar?baz',1)"); 
     stmt.executeUpdate("INSERT INTO Links(URL,pageId) VALUES('http://foo.bar/baz',1)"); 
     stmt.close(); 
     PreparedStatement ps = conn 
      .prepareStatement("SELECT URL,LOCATE ('?', URL) pos FROM Links WHERE pageId=? ORDER BY pos ASC"); 
     ps.setLong(1, 1); 
     ResultSet rs = ps.executeQuery(); 
     while (rs.next()) { 
      System.out.println(rs.getString(1) + ":" + rs.getInt(2)); 
     } 
     rs.close(); 
     ps.close(); 
     conn.close(); 
    } 
} 

Выход:

http://foo.bar/baz:0 
http://foo.bar?baz:15 

Оказывается, что dkatzel верно. Я искал JDBC Spec и не мог найти упоминания о том, что маркер параметра ? будет проигнорирован, если он находится в кавычках, но несколько реализаций парсеров PreparedStatement, которые я нашел (MySql, c-JDBC,), все, кажется, исключают текст в одинарных кавычках из рассмотрение как маркеры параметров.

+0

Возможный дубликат [Является ли спецификация JDBC «запрещена»? от использования в качестве оператора (вне кавычек)?] (http://stackoverflow.com/questions/14779896/does-the-jdbc-spec-prevent-from-being-used-as-an-operator-outside- из-кавычек) –

+1

Предлагаемый дубликат, http://stackoverflow.com/questions/14779896/does-the-jdbc-spec-prevent-from-being-used-as-an-operator-outside-of-quotes специально делает не задайте вопрос о параметре маркера параметра?? в кавычках (задан здесь). –

ответ

4

Уточняется значение ? в спецификации SQL, а спецификация JDBC отсылает к спецификации SQL для этого.

Драйвер не (и не должен) интерпретировать знак вопроса в литерале как заполнитель параметров, так как знак вопроса в строковом литерале является просто символом в строковом литерале. Для получения дополнительной информации см. Главу 5 базы данных SQL: 2011 (ISO-9075-2: 2011).

Таким образом, экранирование не обязательно (и возможно).

+3

Postgres использует знак вопроса как оператор для типов jsonb. Смотрите: http://www.postgresql.org/docs/9.4/static/functions-json.html – hasen

+0

@hasen Хотя это правда, это нужно будет переделать драйвером (который, как я считаю, последними драйверами PostgreSQL JDBC) , как и в JDBC, знак вопроса должен быть только заполнитель параметров. См. Http://stackoverflow.com/questions/14779896/does-the-jdbc-spec-prevent-from-being-used-as-an-operator-outside-of-quotes и http://stackoverflow.com/questions/27573778/postgresql-jsonb-and-jdbc –

+2

@hasen конкретно в последнем драйвере PostgreSQL вам нужно использовать '??' для hstore? оператор. –

3

Вы попробовали? Я думаю, что цитируемые вопросительные знаки в порядке. только «голые» вопросительные знаки должны получить заменить в подготовленном заявлении

+0

Я отредактировал op, чтобы включить тест ... Который подтверждает, что ваше предложение верное. –

6

Если он не работает с драйвером JDBC вы можете связать его как String?,

ps.setString(1, "?"); 
2

Я использовал CHR (63) в своем запросе и помог решить мою проблему.

Вот что я сделал, например: select q'[<div id=['|"]TRD_%%GEN%%['|"].*]' || chr(63) || q'[</div>]' from dual;

Это помогло получать строку как: <div id=['|"]TRD_%%GEN%%['|"].*?</div>

Я тогда использовал этот запрос внутри оператора вставки, и побежал через PreparedStatement. Работал отлично.

Функция CHR является встроенной функцией и может использоваться аналогично другим функциям oracle. Вы можете использовать это, если знаете, что запрос не будет повторяться много раз.

5

В зависимости от используемого драйвера JDBC вы можете сбежать, добавив еще один знак вопроса, например.если вы используете PostgreSQL

https://jdbc.postgresql.org/documentation/head/statement.html

В JDBC, вопросительный знак (?) является заполнителем для позиционных параметров PreparedStatement. Однако существует ряд операторов PostgreSQL, содержащих знак вопроса. Чтобы такие вопросительные знаки в выражении SQL интерпретироваться как позиционные параметры, используйте две вопросительные метки (??) в качестве escape-последовательности. Вы также можете использовать эту escape-последовательность в Statement, но это не требуется. В частности, только в заявлении один оператор (?) может использоваться как оператор.

Смежные вопросы