-
Медвежонок Пятачок © (17.01.12 17:59) [0]Была функция, возвращающая набор данных:
function func1(...) return tSomeTypeSet piplined as
l_res tSomeType
l_query sys_refcursor;
begin
open l_query for sql_query_text with param1;
loop
fetch l_query into l_res;
exit when Query%NOTFOUND;
....
<много логики>
....
pipe row (l_res);
end loop;
end;
Со временем появилась её версия, аналогичная по структуре :
function func2(...) return tSomeTypeSet piplined as
begin
...
end;
Потребовался диспетчер для обоих:
function func_dispatcher(...) return tSomeTypeSet piplined as
l_res tSomeType
l_query sys_refcursor;
l_select_txt varchar2();
begin
l_select_txt := case some_condition
when 1 then 'select * from table(cast(func1(...) as tSomeTypeSet))'
when 2 then 'select * from table(cast(func2(...) as tSomeTypeSet))'
end;
open l_query for l_select_txt with ....;
loop
fetch l_query into l_res;
exit when Query%NOTFOUND;
pipe row (l_res);
end loop;
end;
Проблема : если вызов идет через func_dispatcher, то на строке pipe row (l_res) внутри func1/func2 получаем
ORA-06548: больше строк не требуется (no_data_needed)
Может есть способ избавиться от piplined для func1 и func2 ? -
Кщд (18.01.12 09:45) [1]1. т.е. в случае использования func_dispatcher, данные не возвращаются, хотя должны?
2. с какой целью используется именно pipelined, а не:
function func1(...) return tSomeTypeSet as...;
3. что такое "with" в "open l_query for l_select_txt with ....;"? -
Медвежонок Пятачок © (18.01.12 12:10) [2]пайпланед использовался исторически. когда еще была всего одна версия func1.
открывался курсор, по которому шлепали в лупе. внутри лупа живет некоторое количество логики (типа пост-обработки строки)
далее обработанная строка выдавалась конвейером наружу.
а сама эта функция юзалась на клиенте для получения набора данных.
затем в логике появилась вилка и необходимость в различной обработке строки внутри цикла. Так родилась вторая версия func2 и диспетчер для них.
"with" - это открытие курсора с параметрами -
Медвежонок Пятачок © (18.01.12 12:22) [3]вроде победил.
no_data_needed внутри цикла вызываемой функции - следствие другого исключения внутри цикла вызывающей функции.
то есть ситуация штатная.
Так как внешний цикл обломался, то во внутреннем цикле генерируется исключение, типа "не парься больше, твои данные все равно уже никому не нужны" -
OW © (23.01.12 11:59) [4]спасибо,
хочу так же попробавать
ждал когда разберешься :)
мне нужен DataSet из хранимки
аля вот так пишу:
create or replace package ODACPack
is
TYPE TCursor IS REF CURSOR;
procedure pAAOW (Cur in out TCursor);
end;
create or replace package body ODACPack
is
procedure pAAOW (Cur in out TCursor)
is
begin
OPEN Cur for
SELECT *
FROM applic.dvbt_status
where DATE_INSERT > SYSDATE - 1
order by DATE_INSERT;
end;
end;
что хотел спросить..
а можно как-то сделать, что бы как в MSSQL можно было
Select from pAAOW
join TABLE2..
? -
Медвежонок Пятачок © (23.01.12 13:52) [5]Насколько я понимаю, нужен всего лишь тип (sql) но не на уровне пакета (plsql), а на уровне схемы.
в пакете открываешь курсор с неким запросом, и фетчишь его в цикле в переменную того типа. и делаешь pipe row наружу. -
Кщд (23.01.12 14:44) [6]>OW © (23.01.12 11:59) [4]
1. create type lt_трам-пам-пам...;
2. function get_всё return lt_трам-пам-пам...;
3. select t.id, t.val... bulk collect into переменная_типа_lt_трам-пам-пам...;
4. return переменная_типа_lt_трам-пам-пам;
5. использовать select * from table(get_всё).
pipelined, на мой взгляд, нужно использовать только тогда, когда необходимо как можно быстрее получить первую(ые) записи(в отличие от function get_всё return lt_трам-пам-пам) и/или когда нет возможности создать тип уровня схемы.
Также применимо в случае:
select * from table(pipelined_function) where предикат.
Это как раз случай no_data_needed.))