Oracle 应用管道函数时出现PLS-00653:在 PL/SQL 定义域内不允许有聚集/表函数
创建一个表类型的
create or replace type str_list as table of varchar(300) ;
比如我们创建一个带pipelied 管道函数返回一张表或一个数据源数据的函数test5
create or replace function test5 return str_list pipelined
is
begin
pipe row('line1');
pipe row('line2');
pipe row('line3');
pipe row('line4');
return; --注意这边直接返回就可以了
end;
和创建一个不带该管道函数同样也返回一张表的类型的函数test6
create or replace function test6
return str_list
is
var_out str_list;
begin
var_out:=str_list();
var_out.extend(1);
var_out(1):='line1' ;
var_out.extend(1);
var_out(2):='line2' ;
var_out.extend(1);
var_out(3):='line3' ;
var_out.extend(1);
var_out(4):='line4' ;
return var_out;--这边必须有个输出参数作为返回值
end;
接下来我们创建一个存储过程去调用test5 和 test6
create or replace procedure prc
is
var_out str_list ;
begin
--调用函数test5
--var_out:=test5();
--这边调用带pipelined的函数test5 直接报错PLS-00653: 在 PL/SQL 定义域内不允许有聚集/表函数
--这是因为管道函数 需要用TABLE 操作符从 SQL 查询中调用它 所以这边不能直接赋值
--这边要赋值可以这样修改
select test5() into var_out from dual;
for i in var_out.first()..var_out.last() loop
dbms_output.put_line(var_out(i)) ;
end loop ;
--调用函数test6
select test6() into var_out from dual;
for i in var_out.first()..var_out.last() loop
dbms_output.put_line(var_out(i)) ;
end loop ;
var_out:=test6();
for i in var_out.first()..var_out.last() loop
dbms_output.put_line(var_out(i)) ;
end loop ;
end;
也可以在SQL语句中调用test5和test6:
HR@ prod> select * from table(test5());
COLUMN_VALUE
------------------------------------------------------------------------------------------------------------------------
line1
line2
line3
line4
HR@ prod> select * from table(test6());
COLUMN_VALUE
------------------------------------------------------------------------------------------------------------------------
line1
line2
line3
line4
由此可见非管道的表函数也可以用table函数来转化为可以直接用在SQL语句中的表。
难道是在存储过程中调用pipelined 函数是不行的吗? 答案:是可以的。管道函数调用过程不能直接用":="进行赋值,我们可以采用上面使用赋值方式select test5() into var_out from dual;