#oracle #groovy
#Oracle #groovy
Вопрос:
Итак, я видел кучу потоков об этой ошибке SQL, но я не вижу решения для этой конкретной ситуации. Короче говоря, у меня есть сервер обработки сообщений, который выполняет некоторые сценарии для полезных нагрузок перед передачей полезной нагрузки. Эти скрипты находятся в groovy, и я получаю сообщение об ошибке в моем журнале следующим образом:
WARNING groovy.sql.Sql [process-1{channel}] -
Failed to execute:
select column
from table
where field1 = ?
and field2 in ([468001])
because: ORA-00936: missing expression
Это файл журнала. Когда я на самом деле распечатываю строку, созданную groovy, это следующее:
select column
from table
where field1 = 2.5249083E7
and field2 in (groovy.sql.Sql$35@f7326f4e)
Я предполагаю, что научная нотация — это именно тот способ, которым groovy печатает этот тип, и расширение создает объект, который печатается не очень хорошо.
Фактический groovy-код, который создает эту ошибку, является
sql.eachRow("""
select column
from table
where field1 = $var1
and field2 in (${Sql.expand(varList2.join(','))})
""") { row ->
Часть, которая меня смущает, заключается в том, что этот точный код в этом скрипте отлично выполняется в другой точке в другом groovy script. Это буквально скопировано и вставлено (хотя я этого не писал, и это один из моих немногих groovy-опытов, так что это мало что значит). Если у кого-нибудь есть какие-либо советы, это было бы потрясающе.
Я был бы более чем счастлив, если бы кто-нибудь сказал мне, что я идиот и почему. Это такая простая ошибка, что я предполагаю, что я упускаю что-то очевидное. Я переименовал переменные и имена таблиц / столбцов, но могу заверить вас, что они написаны правильно, и копирование / вставка заполненной версии возвращает данные.
Комментарии:
1. Что
varList2
в запросе, который работает, и что это здесь?2. То же самое в обоих. Это список, но он содержит только одну вещь (целое число, обычно около 6 цифр). Это проблема с нашей моделью данных. Первоначально мы думали, что он будет содержать более одной вещи, но в итоге мы просто выполнили «один к одному» вместо «один ко многим» в настройке таблицы. Отсюда список, в котором никогда не бывает более одного элемента.
3. Все еще происходит сбой с
and field2 = ${varList2.take(1)}
4. Проблема, судя по журналу, заключается в квадратных скобках, которые заключаются в значение. Вам нужно посмотреть, почему
${Sql.expand(varList2.join(','))}
заканчивается как[468001]
, а не просто468001
. В других местах работает тот же шаблон, возможно, вы меняете параметр, который изменяет поведение расширения? Или это частьvarList2
значения перед объединением / расширением? Если у вас все еще та же проблема с=
, можете ли вы привязать ее вместо этого?5. Метод Sql.expand удобен и предполагает безопасность. Но следует отметить, что это потенциальный инструмент для SQL-инъекции . Что может быть продемонстрировано с
varList2 = ['468001) or (1=1']
предоставлением доступа ко всей таблице.
Ответ №1:
Основная причина была диагностирована @tim_yates и @Alex. В любом случае я бы предложил использовать другой подход для привязки СПИСКА IN (тот же подход, который используется в Hibernate).
groovyCon.eachRow
('select * from mytab where x in (' varList2.collect{'?'}.join(',') ')',varList2)
{println it}
Это приводит к s строке SQL
select * from mytab where x in (?,?)
что не только защищает от SQL-инъекций, но и более эффективно, поскольку запросы с той же мощностью в СПИСКЕ IN могут быть повторно использованы без жесткого анализа.
Кроме того, при попытке передать неправильные типы данных вы получаете исключение:
Caught: java.sql.SQLException: Invalid column type