Не может использовать ПОДОБНЫЙ запрос в 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

но я просто, может казаться, не нахожу способ получить их в этом работы.

Что я пропускаю?

30
задан Stefan van den Akker 13 October 2016 в 07:58
поделиться

3 ответа

Во-первых, держатели 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%");

См. также:

59
ответ дан 27 November 2019 в 23:17
поделиться

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

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

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
11
ответ дан 27 November 2019 в 23:17
поделиться

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

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

2
ответ дан 27 November 2019 в 23:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: