Не удается использовать подобный запрос в JDBC PreparedStatement?

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

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 ответов


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

вот фиксированный 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%");

см. также:


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

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

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

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

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

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

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


пропустить ' вокруг ?. Без ', ? - Это параметр. С ним это строка SQL (т. е. такая же, как "?" в Java).

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


можно попробовать:

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

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

"\'" + "?" + "\'"

PreparedStatement ps = con.prepareStatement(
    "select columname from tablename where LOWER(columnname) LIKE LOWER('"+var+"%')");  

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