Не можете использовать LIKE-запрос в JDBC PreparedStatement? - PullRequest
29 голосов
/ 18 мая 2010

Код запроса и запрос:

ps = conn.prepareStatement("select instance_id, ? from eam_measurement where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where resource_group_id = ?) and DSN like '?' order by 2");
ps.setString(1,"SUBSTR(DSN,27,16)");
ps.setInt(2,defaultWasGroup);
ps.setString(3,"%Module=jvmRuntimeModule:freeMemory%");
rs = ps.executeQuery();
while (rs.next()) { bla blah blah blah ...

Возвращает пустое ResultSet.

Посредством базовой отладки я нашел третью связь, которая является проблемой, т.е.

DSN like '?'

Я испробовал все виды вариаций, наиболее разумный из которых, кажется, использовал:

DSN like concat('%',?,'%')

но это не работает, так как я пропускаю ' по обе стороны от объединенной строки, поэтому я пытаюсь:

DSN like ' concat('%',Module=P_STAG_JDBC01:poolSize,'%') ' order by 2

но я просто не могу найти способ заставить их работать.

Что мне не хватает?

Ответы [ 7 ]

58 голосов
/ 18 мая 2010

Во-первых, PreparedStatement заполнители (эти ? вещи) предназначены только для значений столбцов , но не для имен таблиц, имен столбцов, функций / предложений SQL и так далее. Лучше использовать String#format() вместо. Во-вторых, вы должны , а не заключать в кавычки заполнители, такие как '?', это только приведет к неправильному окончательному запросу. Сеттеры PreparedStatement уже выполняют работу по цитированию (и экранированию) за вас.

Вот исправленный SQL:

private static final String SQL = "select instance_id, %s from eam_measurement"
    + " where resource_id in (select RESOURCE_ID from eam_res_grp_res_map where"
    + " resource_group_id = ?) and DSN like ? order by 2");

Вот как это использовать:

String sql = String.format(SQL, "SUBSTR(DSN,27,16)"); // This replaces the %s.
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, defaultWasGroup);
preparedStatement.setString(2, "%Module=jvmRuntimeModule:freeMemory%");

См. Также :

11 голосов
/ 12 июня 2013

Если вы хотите использовать LIKE в подготовленном выражении, а также хотите использовать символы% в LIKE;

написать подготовленное утверждение как обычно ".... LIKE? ...." и при присвоении значения параметра вопросительному знаку использовать

ps.setString(1, "%" + "your string value" + "%");

Это будет работать:)

11 голосов
/ 18 мая 2010

Есть две проблемы с вашим утверждением. Вы должны понимать, как работают переменные связывания. Запрос не обрабатывается путем замены символов ? вашими параметрами. Вместо этого оператор компилируется с заполнителями, а затем во время выполнения фактические значения параметров передаются в БД.

Другими словами, вы анализируете следующий запрос:

SELECT instance_id, :p1
  FROM eam_measurement
 WHERE resource_id IN (SELECT RESOURCE_ID 
                         FROM eam_res_grp_res_map 
                        WHERE resource_group_id = :p2)
   AND DSN LIKE '?'
 ORDER BY 2

Я почти уверен, что последний параметр будет проигнорирован, поскольку он находится в строке символов с разделителями. Даже если это не игнорируется, не имеет смысла иметь символы ', потому что Oracle не будет связывать параметр в строке (я удивлен, что это не вызвало никакой ошибки, вы ловите исключения?).

Теперь, если вы замените DNS LIKE '?' на DSN LIKE ? и свяжете "%Module=jvmRuntimeModule:freeMemory%", это будет иметь смысл и должно вернуть правильные строки.

У вас все еще есть проблема с вашим первым параметром, он не будет выполнять то, что вы ожидаете, т. Е. Запрос, который будет выполнен, будет эквивалентен следующему запросу:

SELECT instance_id, 'SUBSTR(DSN,27,16)'
  FROM ...

, что совсем не то же самое, что

SELECT instance_id, SUBSTR(DSN,27,16)
  FROM ...

Я бы предложил синтаксический анализ (= prepareStatement) следующего запроса, если вы ожидаете, что SUBSTR будет динамическим:

SELECT instance_id, SUBSTR(DSN,?,?)
  FROM eam_measurement
 WHERE resource_id IN (SELECT RESOURCE_ID 
                         FROM eam_res_grp_res_map 
                        WHERE resource_group_id = ?)
   AND DSN LIKE ?
 ORDER BY 2
2 голосов
/ 18 мая 2010

Опустить ' вокруг ?. Без ', ? является заполнителем для параметра. С его помощью это строка SQL (т. Е. Такая же, как "?" в Java).

Затем вы должны объединить строку на стороне Java; Вы не можете передавать функции SQL в качестве параметров для запросов; только базовые значения (например, строка, целое число и т. д.), поскольку драйвер JDBC преобразует параметр в тип SQL, ожидаемый базой данных, и не может выполнять функции SQL на этом этапе.

0 голосов
/ 10 сентября 2016
PreparedStatement ps = con.prepareStatement(
    "select columname from tablename where LOWER(columnname) LIKE LOWER('"+var+"%')");  

Здесь var - это переменная, в которой хранится значение, которое необходимо найти ...

0 голосов
/ 14 сентября 2014

Это должно работать:

"\'" + "?" + "\'"
0 голосов
/ 03 апреля 2013

Вы можете попробовать:

String beforeAndAfter = "%" + yourVariable + "%";
...