:: Не фоксом единым
Экранирование апострофа Оракл динамический запрос
boba
Автор

Сообщений: 6269
Откуда: Медвежьи озера-
Дата регистрации: 26.03.2001
Экранирование ' для
imidiate execute
Есть огромный статический по тексту запрос,
который пытаюсь сделать динамическим
Часть колонок в нем меняются ( разные имена и число)
в зависимости от некого справочника
Застрял с глупостью
В исходном не динамическом запросе есть куски
типа
'{'||substr()||'}'
case when a= 'bbb' then 'ccc' else 'ddd'
Заменил подставляемые вещи переменными до запроса
var:= '{' ;
var1:='}';
var2 :='||' ;
А в запросе подставляю их параметрами :var||substr ...
Получается верно только при использовании using
в противном случает строка для запроса формируется неверно
типа case a :={ then bbb ( без кавычек
Как же туда в строку формируемого запроса засунуть
исходный вариант '{'||substr()||'}'

С using выходит верно,
но число мест замены очень большое,
постоянно путаюсь с правильным местом этого самого
using

Очень хочется без него
без потери одиночный апострофов и '||'
Ratings: 0 negative/0 positive
Re: Экранирование апострофа Оракл динамический запрос
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
При генерации текстов запросов надо просто удвоить кавычку.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Экранирование апострофа Оракл динамический запрос
boba
Автор

Сообщений: 6269
Откуда: Медвежьи озера-
Дата регистрации: 26.03.2001
select case
when f10022 != ' ' then
'{' || substr(f10022, 1, 6) || '}' || substr(f10022, 7)
else
' '
end as f10022,
case
when f10023 != ' ' then
'{' || substr(f10023, 1, 6) || '}' || substr(f10023, 7)
else
' '
end as f10023,

___________________
select case
when ss.nminref = '_КОНСОЛИДАЦИЯ' then
' '
else
aa.nminref
end as f10022,
case
when ss.nminref = '_КОНСОЛИДАЦИЯ' then
' '
else
bb.nminref
end as f10023,

__________________________
case
when ss.nminref = '_КОНСОЛИДАЦИЯ' then
'_КОНСОЛИДАЦИЯ'
else
'Не Консолидация'
end as f6004,
___________________________
case
when nvl(t.value, '0') = 0 then
tt.nminref
else
'_КОНСОЛИДАЦИЯ'
end as nminref,

Пытаюсь заменить так
lcbl := ' ';
lbl := '{';
lbr := '}';
lnvl :='0';
lccons := '_КОНСОЛИДАЦИЯ';
nodef := 'NULL НЕ ОПРЕДЕЛЕНО';
lcncons := 'Не Консолидация';
l_query := 'select case when f10022 != :lcbl';
l_query := l_query || ' then :lbl '|| '|| substr(f10022, 1, 6) ||:lbr '||
'|| substr(f10022, 7) else :lcbl ' || ' end as f10022,';
l_query := l_query || ' case when f10023 != :lcbl' || ' then :lbl '||
'|| substr(f10023, 1, 6) :lbr ' || ' || substr(f10023, 7) ';
l_query := l_query || ' else :lcbl ';
l_query := l_query || ' end as f10023,';
Ratings: 0 negative/0 positive
Re: Экранирование апострофа Оракл динамический запрос
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Если ты хочешь использовать именно параметры, то естественно в динамический запрос они передаются через USING и никак иначе.
Если ты просто хочешь генерировать текст запроса, то нужно именно конкатенацией собирать строки, а не использовать :param и в этом случае для вставки в строку кавычки её нужно удвоить.
пример со связываемой переменной.
sql_stmt := 'SELECT * FROM emp WHERE name = :1';
p_name := 'John';
EXECUTE IMMEDIATE sql_stmt INTO emp_rec USING p_name;
Аналогичный пример с просто текстом запрооса, где должны быть кавычки:
sql_stmt := 'SELECT * FROM emp WHERE name = ''John''';
EXECUTE IMMEDIATE sql_stmt INTO emp_rec;
Ну или то же самое с "конструированием" текста запроса:
p_name := 'John';
sql_stmt := 'SELECT * FROM emp WHERE name = ''' || p_name || '''';
EXECUTE IMMEDIATE sql_stmt INTO emp_rec;
Надеюсь движок форума не скушает множественные кавычки
P.S. связываемые переменные можно использовать ровно в тех же самых "контекстах" как и при посылке обычных запросов. Т.е. к примеру так можно
SELECT * FROM emp WHERE name = :param
а так нельзя
SELECT * FROM :param_with_table_name WHERE :param_with_field_name = 123
Т.е. параметризовать имена таблиц или полей (или любых других "объектов словаря БД") или собственно ключевые слова команд нельзя. Для такой параметризации ТОЛЬКО генерация текста запроса подходит - БЕЗ использования параметров и, соответственно, USING (точнее без использования параметров для этих самых имён таблиц/полей/ключевых слов - для собственно "значений" параметры можно использовать всегда).


------------------
WBR, Igor




Исправлено 1 раз(а). Последнее : Igor Korolyov, 07.03.19 22:45
Ratings: 0 negative/0 positive
Re: Экранирование апострофа Оракл динамический запрос
boba
Автор

Сообщений: 6269
Откуда: Медвежьи озера-
Дата регистрации: 26.03.2001
Да, Игорь
Фактически подходит только вариант
с using
так как процедура также имеет in параметры,
которые тоже нужно отдать в динамический
текст запроса, сделанный из статического
Второй день бьюсь с ошибкой-
не все переменные привязаны.
В тексте ошибки ссылается на первую строчку
в запросе, а строчек полторы сотни.
То есть ошибка не в первой строке.
Число параметров -верное.
Беру уже текст , который сгенерился,
правлю и запускаю.
Черт знает, где ошибка.
Сижу режу на мелкие кусочки ,проверяю каждый
Это довольно странно, так как сам исходный статичский текст
работает исправно уже года два, и естественно
тоже писался и отлаживался мелкими кусочками.
Ratings: 0 negative/0 positive
Re: Экранирование апострофа Оракл динамический запрос
boba
Автор

Сообщений: 6269
Откуда: Медвежьи озера-
Дата регистрации: 26.03.2001
В общем такое дело
После вызова execute immediate
поставил exception
с номером ошибки и текстом сформированного
запроса.
Беру это самый запрос в новое окно,
правлю там разорванные на разные строки
слова и запускаю.
Никакой ошибки,
запрос дает результат.
Сегодня наконец увидел,
что строка , в которой коплю текст запроса,
объявленная как varchar максимальной длительности
на некой строке склейки меняет тип на long
До этой строки был виден в переменной ее текст,
а после нее -long
Если сократить запрос до этого места,
он выполняется через вызова execute immediate
Как только переменная буфера запроса меняет тип,
запрос валится. Причем ошибка -несовместимость типов.

Если оставить в запросе параметры,
то ошибка другая- не все переменные привязаны.

Но опять таки текст запроса, выведенный
в анализе ошибки при переносе в новое окно запроса
с редактированием разорванных на разные строки переменные
выполняется без ошибки
Тексты рвутся потому как вывожу строчками по 150 символов текст
запроса. Не совсем понимаю, что с эти теперь делать.
Ratings: 0 negative/0 positive
Re: Экранирование апострофа Оракл динамический запрос
pasha_usue

Сообщений: 3649
Откуда: Е-бург
Дата регистрации: 06.10.2006
Где-то конкатенатор перепутан? Вместо || используется +?



Исправлено 1 раз(а). Последнее : pasha_usue, 12.03.19 20:22
Ratings: 0 negative/0 positive
Re: Экранирование апострофа Оракл динамический запрос
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
1) Менять подход. Текст запроса не помещающийся в 32К символов - это нонсенс.
2) Ты не указываешь используемую версию - в старых версиях execute immediate принимал только типы char/varchar2 - и в принципе не мог исполнять скрипты длиннее 32К символов. В более менее современных он принимает ещё и CLOB - НО с CLOB работают чуть по иному нежели с varchar2. С LONG, насколько я в курсе, не работает ни одна версия. И автоматом тип переменной (где накапливается текст запроса) оракл не меняет - не может varchar2 превратится в long.
Вообще раньше для особо больших скриптов рекомендовался пакет DBMS_SQL - там скрипт "построчно" в массив помещался.

Но ещё раз советую обратить внимание на п.1 и что-то "поменять в консерватории". Есть масса самых разных способов обработать данные - включая табличные функции. Мега-запросы на 50 страниц текста это уродство хоть в статическом, хоть в динамическом видах.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Экранирование апострофа Оракл динамический запрос
boba
Автор

Сообщений: 6269
Откуда: Медвежьи озера-
Дата регистрации: 26.03.2001
Игорь
Ситуация довольно странная
Оракл 11
Длина строки, даже двух строк ,
которые я клею для динамического запроса
всего около 22 строки по 150 символов к моменту вызова
execute imidiate
Ломается тип где-то посередине формирования второй
длинной переменной. Вот этого я в упор не пойму,
что это за хрень такая.
Строка, где все ломается, довольно банальная,
ничем не отличается от строк выше и ниже.
Есть другие чужие процедуры,которые клеят
строки для помещение в лонг поле,
не для запроса , где никакой такой смены типа
не происходит.
Способов решить задачу действительно несколько.
Это самое изменение содержания справочников,
которое требует замены текста происходит
довольно редко.
Я спокойно менял свои статические процедуры
в этом случае по звонку буха, который этим занимается.
Просто хочется сделать вариант независимый от программиста.
Вчера сделал работающую вещь, но она диковата.
Считал на фокс текст статической процедуры ( это не трудно,
только склеить потом строки и добавить create or replace),
запросил справочник,
изменил изменил программно в тексте 2 места, требующих
нового списка из справочника,
снова послал из фокса этот текст назад на Оракл.
Все, получилась новая статическая процедура.
Только нехорошо рядовому пользователю давать такой доступ.
А так даже можно приклеить какой никакой интерфейс.
Ratings: 0 negative/0 positive
Re: Экранирование апострофа Оракл динамический запрос
boba
Автор

Сообщений: 6269
Откуда: Медвежьи озера-
Дата регистрации: 26.03.2001
Прошу прощения за потерянное время и некую
дезинформацию
Несоответствие типов оказалось
вовсе из другой песни
Вместо комментированного
-- execute immediate (l_query)
-- into p_cursor ;
пишу
open p_cursor for l_query;
и все работает.
Варианты с execute imidiate
брал из готовых примеров,
которые мы работали.
Причем, p_cursor объявлен
как refcursor
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 4 (Гостей: 4)

© 2000-2024 Fox Club 
Яндекс.Метрика