我在oracle中有此函数,应该以逗号分隔的数字列表作为输入,并迭代每个数字,然后将其传递给另一个函数,然后通过管道输出。
create or replace FUNCTION FUNC1(num_list varchar2,separator varchar2) RETURN typeAs PIPELINED
as
begin
FOR nums in (select regexp_substr(num_list,'[^'||separator||']+', 1, level) num from dual
connect by regexp_substr(num_list, '[^'||separator||']+', 1, level) is not null)
loop
PIPE ROW(typeA(NVL(nums.num,0) ,NVL(FUNC2(nums.num),0)));
end loop;
end;
注意:
create or replace TYPE typeA AS OBJECT (num varchar2(20),val varchar2(20))
create or replace TYPE typeAs AS TABLE OF typeA;
如果传递给FUNC2时列表中的所有数字将返回非null的输出,则该函数正常工作。但是,如果一个数字在传递给FUNC2时返回null,则列表中的所有后续数字都不会显示在FUNC1的输出中。
编辑:结果:
select * from table(FUNC1('1111,4333,121212',',')) :
output:
-----------------
1111 | val1
其他两个数字未显示在输出中,因为FUNC2('4333')为null,因为知道FUNC2('121212')具有值。 :
select * from table(FUNC1('1111,2222,121212',',')) :
output:
-----------------
1111 | val1
2222 | val2
121212 | val3
答案 0 :(得分:2)
对于输入值4333,如果REST_FRAMEWORK = {
...
'DEFAULT_PERMISSION_CLASSES': ( 'rest_framework.permissions.IsAdminUser', ),
...
}
抛出func2
异常而不是返回null,您将看到这种效果。如果该函数正在从另一个表中查找值,则可能有意义
因为您对no_data_found
的调用是在SQL上下文中进行的,因此异常是致命的,并且在遇到异常时执行将失败,而无需任何预兆。如果从PL / SQL上下文调用func1
,则会看到异常。
作为具有虚拟func1
的演示:
func2
和您的原始功能:
create or replace function func2(p_num number) return varchar2 as
begin
if p_num = 4333 then
raise no_data_found;
end if;
return case p_num
when 1111 then 'val1'
when 2222 then 'val2'
when 121212 then 'val3'
else null
end;
end func2;
/
您可以更改create or replace FUNCTION FUNC1(num_list varchar2,separator varchar2) RETURN typeAs PIPELINED
as
l_val varchar2(20);
begin
FOR nums in (select regexp_substr(num_list,'[^'||separator||']+', 1, level) num from dual
connect by regexp_substr(num_list, '[^'||separator||']+', 1, level) is not null)
loop
PIPE ROW(typeA(NVL(nums.num,0) ,NVL(FUNC2(nums.num),0)));
end loop;
end;
/
select * from table(FUNC1('1111,4333,121212',','));
NUM VAL
-------------------- --------------------
1111 val1
select * from table(FUNC1('1111,2222,121212',','));
NUM VAL
-------------------- --------------------
1111 val1
2222 val2
121212 val3
以显式调用该函数并处理异常:
func1
或者您可以更改create or replace FUNCTION FUNC1(num_list varchar2,separator varchar2) RETURN typeAs PIPELINED
as
l_val varchar2(20);
begin
FOR nums in (select regexp_substr(num_list,'[^'||separator||']+', 1, level) num from dual
connect by regexp_substr(num_list, '[^'||separator||']+', 1, level) is not null)
loop
begin
l_val := FUNC2(nums.num);
exception
when no_data_found then
l_val := null;
end;
PIPE ROW(typeA(NVL(nums.num,0) ,NVL(l_val,0)));
end loop;
end;
/
select * from table(FUNC1('1111,4333,121212',','));
NUM VAL
-------------------- --------------------
1111 val1
4333 0
121212 val3
select * from table(FUNC1('1111,2222,121212',','));
NUM VAL
-------------------- --------------------
1111 val1
2222 val2
121212 val3
,以便它捕获异常并返回null,或者更改其查询以使其一开始就无法获取异常。这是否合适取决于您-可以在需要传播异常的其他地方使用它...
(顺便说一下,由于func2
返回一个字符串,因此func2
也应该确实使用字符串-即使该字符串是nvl()
,因为它已隐式转换为现在。)