嵌套PIPELINED函数

时间:2016-01-20 09:59:27

标签: oracle plsql pipelined-function

create type data_type_1 as object (x number, y number)
/

create type table_type_1 as table of data_type_1
/

create or replace package xyz AS
      function main_xyz return table_type_1 pipelined;
      function sub_func return table_type_1 pipelined;
      function sub_func1 return table_type_1 pipelined;
end xyz;
/

create package body XYZ AS
    function main_xyz return data_type_1 pipelined is
        begin 
        --code
        --pipe row(sub_func); --edit_1
        FOR rec in (select * from table(sub_func1(x,y))) LOOP
               pipe row(rec);
        END LOOP;
        end;
    --function sub_func return data_type_1 pipelined is --edit_1
        --begin --edit_1
        --code --edit_1
        --pipe row(def); --def is data_type_1 --edit_1
        --end; --edit_1
     function sub_func_1(x in number, y in number) return data_type_1 pipelined is
        begin 
        --code
        loop
        pipe row(abc); --abc is data_type_1
        end loop;
        end;
 end;
 create package body ABC AS
     function main_ABC is
        begin 
        --code
        FOR rec in (select * from table(main_xyz)) LOOP
               pipe row(rec);
        END LOOP;
        end;
 end;

我获得的错误是......

  

在调用sub_func1的main_xyz块中显示错误。

     

[错误] PLS-00382():PLS-00382:表达式类型错误   [错误] PLS-00306():PLS-00306:调用
中的参数数量或参数类型错误   [错误] ORA-00904():PL / SQL:ORA-00904 ::无效标识符
  [错误] PLS-00364():PLS-00364:循环索引变量'REC'使用无效

上面的代码有什么问题?为什么?

1 个答案:

答案 0 :(得分:2)

您的函数正在返回data_type_1,并且表集合也在尝试使用它。但是两者都需要一个集合类型,即使你期望它们只返回一个值(在这种情况下,没有多少点流水线)。您不能直接管道集合类型,管道集合的成员。所以data_type_1应该是标量或对象/记录类型,你需要另一种类型的集合。

create type data_type_1 as object (x number, y number)
/

create type table_type_1 as table of data_type_1
/

create or replace package xyz AS
  function main_xyz return table_type_1 pipelined;
  function sub_func return table_type_1 pipelined;
  function sub_func1 return table_type_1 pipelined;
end xyz;
/

create or replace package body xyz as
  function main_xyz return table_type_1 pipelined is
  begin 
    --code
    for rec in (select * from table(sub_func)) loop
      pipe row(data_type_1(rec.x, rec.y));
    end loop;
    for rec in (select * from table(sub_func1)) loop
      pipe row(data_type_1(rec.x, rec.y));
    end loop;
  end;

  function sub_func return table_type_1 pipelined is
    def data_type_1;
  begin 
    --code
    pipe row(def); --def is data_type_1
  end sub_func;

  function sub_func1 return table_type_1 pipelined is
    abc data_type_1;
  begin 
    --code
    loop
      pipe row (abc); --abc is data_type_1
    end loop;
  end sub_func1;
end xyz;
/

所以我添加了现有data_type_1的表类型,并更改了函数定义以返回该表类型。 pipe row仍然使用data_type_1 - 每个都是表格类型中的一行。你的循环需要查询其光标,而不是直接调用table(),所以我也改变了。 pipe row(sub_func);也需要与查询类似。

您只是将其标记为PL / SQL,但是因为您可能打算从纯SQL调用main_xyz,并且因为您从这些循环中的SQL上下文调用子函数,data_type_1并且table_type_1需要在模式级别而不是在PL / SQL中创建。 (这有changed a bit in 12c但不足以帮助到这里。)

如果你想将它们作为PL / SQL类型(在包规范中声明),那么就无法从非PL / SQL上下文中调用该函数,并且你必须用一个调用来替换这些循环函数后跟迭代返回的集合。