Вы увидите этот эффект, если func2
выдает исключение no_data_found
, а не возвращает ноль, для входного значения 4333. Это, вероятно, имеет смысл, если эта функция ищет значение из другой таблицы.
Поскольку ваш вызов func1
находится в контексте SQL, это исключение является молчаливым фатальным, и выполнение встречается, когда оно встречается, без каких-либо указаний на ошибку.Если бы вы вызвали func1
из контекста PL / SQL, вы бы увидели исключение.
В качестве демонстрации с пустышкой 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
db <> fiddle demo .
Или вы можете изменить func2
, чтобы он перехватывал исключение и возвращал ноль, или изменял свой запрос, чтобы он не мог получить исключение в первую очередь.Насколько это уместно, решать вам - его можно использовать в других местах, где необходимо распространить исключение ...
(Между прочим, поскольку func2
возвращает строку, nvl()
для этого следуетдействительно используйте строку - даже если это 0
, поскольку она неявно преобразуется в настоящее время.)