2011-10-25 19 views
2

我目前正在使用此代码块从我的函数返回行的集合。从打包函数中返回集合以用于select

--Source: http://www.adp-gmbh.ch/ora/plsql/coll/return_table.html 

create or replace type t_col as object (
i number, 
n varchar2(30) 
); 
/
create or replace type t_nested_table as table of t_col; 
/
create or replace function return_table return t_nested_table as 
    v_ret t_nested_table; 
begin 
    v_ret := t_nested_table(); 

    v_ret.extend; 
    v_ret(v_ret.count) := t_col(1, 'one'); 

    v_ret.extend; 
    v_ret(v_ret.count) := t_col(2, 'two'); 

    v_ret.extend; 
    v_ret(v_ret.count) := t_col(3, 'three'); 

    return v_ret; 
end return_table; 
/

这一点我通过发出SQL

select * from table(return_table); 

对象类型不能在一个包中定义的来电,我尝试使用它的工作(在PL/SQL)记录类型,但我无法选择从我能在这里以同样的方式。

如何使用包内的函数实现此结果?

回答

6

您可以在包中使用SQL对象或使用流水线函数(使用10gr2测试)。使用SQL对象很简单,您的实际功能可以在包中使用。

这里是你如何可以使用管道函数有一个记录类型:

SQL> CREATE OR REPLACE PACKAGE my_pkg IS 
    2  TYPE t_col IS RECORD(
    3  i NUMBER, 
    4  n VARCHAR2(30)); 
    5  TYPE t_nested_table IS TABLE OF t_col; 
    6  FUNCTION return_table RETURN t_nested_table PIPELINED; 
    7 END my_pkg; 
    8/

Package created 
SQL> CREATE OR REPLACE PACKAGE BODY my_pkg IS 
    2  FUNCTION return_table RETURN t_nested_table PIPELINED IS 
    3  l_row t_col; 
    4  BEGIN 
    5  l_row.i := 1; 
    6  l_row.n := 'one'; 
    7  PIPE ROW(l_row); 
    8  l_row.i := 2; 
    9  l_row.n := 'two'; 
10  PIPE ROW(l_row); 
11  RETURN; 
12  END; 
13 END my_pkg; 
14/

Package body created 

SQL> select * from table(my_pkg.return_table); 

     I N 
---------- ------------------------------ 
     1 one 
     2 two 

台前幕后发生的是,甲骨文明白,既然你想用你的函数在一个查询(因为PIPELINED关键字),您将需要SQL对象,所以在幕后创建这些对象为您提供:

SQL> select object_name 
    2 from user_objects o 
    3 where o.created > sysdate - 1 
    4  and object_type = 'TYPE'; 

OBJECT_NAME 
-------------------------------------------------------------------------------- 
SYS_PLSQL_798806_24_1 
SYS_PLSQL_798806_DUMMY_1 
SYS_PLSQL_798806_9_1 

SQL> select text from user_source where name='SYS_PLSQL_798806_9_1'; 

TEXT 
-------------------------------------------------------------------------------- 
type  SYS_PLSQL_798806_9_1 as object (I NUMBER, 
N VARCHAR2(30)); 
+0

感谢您的回答,当你说“用你的包内SQL对象”,他们仍需要在包裹外面定义吗?我试图在一个包中定义一个对象,并得到“PLS-00540:在这种情况下不支持的对象。”。我想尝试将所有的类型定义保存在它们使用的包中。 – TownCube

+0

是SQL对象始终在包外部定义。在包内定义的PLSQL记录类型不能从SQL访问。如果你想从SELECT中查询表对象,你将需要SQL对象(定义为一个包之外的类型)。我个人倾向于使用一致命名的SQL对象,而不是由Oracle选择的任意名称。 –

0
create or replace type t_col as object (
    i number, 
    n varchar2(30) 
); 
/

create or replace package foo as 
    type t_nested_table is table of t_col; 
    function return_table return t_nested_table pipelined; 
end; 
/
show errors 

create or replace package body foo as 
    data t_nested_table := t_nested_table(t_col(1, 'one'), 
             t_col(2, 'two'), 
             t_col(3, 'three')); 

    function return_table return t_nested_table pipelined as 
    begin 
    for i in data.first .. data.last loop 
     pipe row(data(i)); 
    end loop; 
    return; 
    end; 
end; 
/
show errors 

column n format a10 
select * from table(foo.return_table); 

     I N 
---------- ---------- 
     1 one 
     2 two 
     3 three