#sql #oracle #dynamic #native
#sql #Oracle #динамический #собственный
Вопрос:
Я схожу с ума по этому поводу. Я довольно новичок в динамическом SQL, поэтому, возможно, я просто не задаю Google правильный вопрос, но вот что я пытаюсь сделать… У меня есть запрос с динамическим SQL. Когда я запускаю этот запрос, он выдает несколько строк. Все эти строки (около 30) составляют один запрос объединения. Я могу скопировать все эти строки, вставить в новый запрос и запустить — работает нормально, но что мне нужно сделать, так это выполнить все это в одном запросе. Я просмотрел примеры использования execute immediate и fetch, но, похоже, я не могу заставить их фактически выдавать данные…в итоге они просто говорят что-то вроде «Выполнено успешно», но на самом деле не создают никаких результирующих строк. Результирующее имя столбца приведенного ниже SQL-кода — «qry_txt» — вместо того, чтобы выдавать его по номинальной стоимости, я хочу выполнить его как запрос. Опять же, я, возможно, плохо формулирую это, но я в основном пытаюсь превратить 2 запроса (с включенным шагом копирования / вставки вручную) в один запрос. Надеюсь, это имеет смысл…
Вот мой SQL:
Select CASE when
lead(ROWNUM) over(order by ROWNUM) is null then
'SELECT '||''''||T.TABLE_NAME||''''||' as TABLE_NAME,'||''''||T.COLUMN_NAME||''''||' as COLUMN_NAME, cast('|| T.COLUMN_NAME ||' as
varchar2(100)) as SAMPLE_DATA ||
from rpt.'||T.TABLE_NAME ||' where '||T.COLUMN_NAME||' is not null and ROWNUM=1;'
else
'SELECT '||''''||T.TABLE_NAME||''''||' as TABLE_NAME,'||''''||T.COLUMN_NAME||''''||' as COLUMN_NAME, cast('|| T.COLUMN_NAME ||' as
varchar2(100)) as SAMPLE_DATA from rpt.'||T.TABLE_NAME ||' where '||T.COLUMN_NAME||' is not null and ROWNUM=1 union ' end as qry_txt
from all_tab_columns t where T.OWNER='rpt' and T.DATA_TYPE != 'BLOB' and T.DATA_TYPE != 'LONG' and T.TABLE_NAME = 'NME_DMN'
ORDER BY ROWNUM asc;
Комментарии:
1. Ваша цель — открыть курсор, который возвращается вызывающему объекту, который затем извлекает строки (это проще и может быть сделано с помощью
execute immediate
). Или вам нужен блок PL / SQL, который извлекает все строки (что сложнее и почти наверняка предполагает более сложный маршрут с использованиемdbms_sql
пакета)?2. Из того, что я читал, открытие курсора звучит как правильный путь. Да, мне нужно извлечь все строки, как если бы я выполнял прямой запрос select. Пока я заканчиваю со строками, я открыт для любого метода, но самый простой был бы лучшим с точки зрения моей возможности повторить технику … 😉
3. Если вы хотите открыть курсор, который возвращается вызывающему, вызывающий не может быть блоком PL / SQL, который извлекает данные (ну, это может быть, если вы используете 12.1, и вы готовы стать еще более сложным). Вы могли бы вернуть курсор, скажем,
SQL*Plus
или в приложение C #, которое затем могло бы извлекать данные. Если вы хотите иметь блок PL / SQL, который извлекает все строки, вам понадобится более сложныйdbms_sql
путь. Я не уверен, какой из них действительно работает для вас.4. Я бы сказал, если это не функция native sql в oracle (из коробки), то, вероятно, это не сработало бы для меня. Все примеры dbms_sql, с которыми я сталкивался, терпят неудачу для меня. Итак, возможно, открытие курсора не является ответом? Видите ли вы какой-либо другой готовый метод, который я могу использовать для достижения того, чего я хочу? Это моя первая попытка сделать что-то подобное, так что, возможно, это даже невозможно. Судя по результатам, которые я вижу в Google, я первый человек на планете, пытающийся это сделать, так что, возможно, это невыполнимо…
5. Это в высшей степени выполнимо. Используя
execute immediate
, вы можете с радостью вернуть курсор в приложение, которое знает, как опрашивать курсор, чтобы определить такие вещи, как количество и тип столбцов, чтобы извлечь данные.SQL*Plus
знает, как это сделать, как это делает, реально, любой клиентский API (JDBC / ODBC / OLE DB / etc.). Если вы хотите написать блок PL / SQL, который извлекает данные, вам нужно написать более сложныйdbms_sql
код. Обаexecute immediate
иdbms_sql
существуют «из коробки». Одно намного проще другого.
Ответ №1:
Вы не можете написать динамический запрос в SQL. Для этого необходимо использовать блок PLSQL. Пожалуйста, посмотрите, как вы можете это сделать. PS: код не тестируется.
declare
var1 <decalration same of column in select list> ;
var2 <decalration same of column in select list> ;
var3 <decalration same of column in select list> ;
....
varn ;
begin
for i in ( SELECT LEAD (ROWNUM) OVER (ORDER BY ROWNUM) COl1
FROM all_tab_columns t
WHERE T.OWNER = 'rpt'
AND T.DATA_TYPE != 'BLOB'
AND T.DATA_TYPE != 'LONG'
AND T.TABLE_NAME = 'NME_DMN'
ORDER BY ROWNUM ASC)
Loop
If i.col1 IS NULL Then
execute immediate 'SELECT '
|| ''''
|| T.TABLE_NAME
|| ''''
|| ' as TABLE_NAME,'
|| ''''
|| T.COLUMN_NAME
|| ''''
|| ' as COLUMN_NAME, cast('
|| T.COLUMN_NAME
|| ' as
varchar2(100)) as SAMPLE_DATA ||
from rpt.'
|| T.TABLE_NAME
|| ' where '
|| T.COLUMN_NAME
|| ' is not null and ROWNUM=1' into var1 , var2 ,var3 ....varn;
Else
execute immediate 'SELECT '
|| ''''
|| T.TABLE_NAME
|| ''''
|| ' as TABLE_NAME,'
|| ''''
|| T.COLUMN_NAME
|| ''''
|| ' as COLUMN_NAME, cast('
|| T.COLUMN_NAME
|| ' as
varchar2(100)) as SAMPLE_DATA from rpt.'
|| T.TABLE_NAME
|| ' where '
|| T.COLUMN_NAME
|| ' is not null and ROWNUM=1' into var1 , var2 ,var3 ....varn;
end if;
End Loop;
exception
when others then
dbms_output.put_lin(sqlcode ||'--'||sqlerrm);
End;
Комментарии:
1. Я запустил это и получил эту ошибку: Ошибка поиска ORA-06550: строка 2, столбец 8: PLS-00103: обнаружен символ «<» при ожидании одного из следующих: постоянная таблица исключений длинная двойная ссылка символ время интервал временной метки дата двоичный национальный символ nchar
2. Я просто помогаю вам с телом. Это не фактический рабочий код. Я просто помог вам с тем, как вы можете работать дальше. Также мои комментарии встроены. Просто следуйте синтаксису и соответствующим образом измените свой код
3. Боюсь, я недостаточно знаю о вашей технике или ошибках, которые я получаю в настоящее время, чтобы заставить это работать на меня. Все еще пытаюсь…
4. Вы можете опубликовать код, который вы пытаетесь. Либо я, либо кто-то другой обязательно вам поможет. не забудьте пометить вопрос в разделе Oracle и опубликовать ошибку, с которой вы столкнулись
5. Я изменил ваш код, и теперь он выполняется, но он просто говорит «выполнено успешно», на самом деле он не возвращает строки. Код здесь: pastebin.com/XJLnb9Zi