嵌套的 PIPELINED 函数

Nested 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;

我得到的错误是...

Error is showed in the block of main_xyz where sub_func1 is called.

[Error] PLS-00382 (): PLS-00382: expression is of wrong type
[Error] PLS-00306 (): PLS-00306: wrong number or types of arguments in call to
[Error] ORA-00904 (): PL/SQL: ORA-00904: : invalid identifier
[Error] PLS-00364 (): PLS-00364: loop index variable 'REC' use is invalid

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

您的函数正在 returning data_type_1,并且 table 集合也在尝试使用它。但是两者都需要一个集合类型,即使您希望它们只有 return 一个值(在这种情况下没有太多点流水线)。您不能直接通过管道传输集合类型,而是通过管道传输集合的成员。所以 data_type_1 应该是标量或 object/record 类型,你需要另一种类型,它是这些的集合。

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 的 table 类型,并将函数定义更改为 return 类型 table。 pipe row 仍然使用 data_type_1 - 每个都是 table 类型中的一行。您的循环需要查询其游标,而不是直接调用 table(),因此我也对其进行了更改。 pipe row(sub_func); 也需要对查询进行类似的循环。

您只将此标记为 PL/SQL,但因为您可能打算从普通 SQL 调用 main_xyz,并且因为您是从 sub-functions 调用 SQL 这些循环中的上下文,data_type_1table_type_1 需要在架构级别创建,而不是在 PL/SQL 中创建。 (这有 changed a bit in 12c 但不足以帮助这里)。

如果你想让它们作为 PL/SQL 类型,在包规范中声明,那么你不能从非 PL/SQL 上下文调用函数,你必须用对函数的调用替换循环,然后对 returned 集合进行迭代。