Конференция "Базы" » Oracle piplined function
 
  • Медвежонок Пятачок © (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.))
 
Конференция "Базы" » Oracle piplined function
Есть новые Нет новых   [134431   +10][b:0][p:0.001]