Oracle 函数在子程序中出现异常后恢复执行
我在一个子程序中引发了一个异常,我希望看到调用函数在此时停止执行。然而,调用函数继续处理,就好像什么都没发生一样,我不明白为什么 我的函数如下所示:Oracle 函数在子程序中出现异常后恢复执行,oracle,exception,plsql,Oracle,Exception,Plsql,我在一个子程序中引发了一个异常,我希望看到调用函数在此时停止执行。然而,调用函数继续处理,就好像什么都没发生一样,我不明白为什么 我的函数如下所示: FUNCTION getFooCursor (i_blah IN VARCHAR) RETURN t_ref_cursor IS v_sum_variable NUMBER; BEGIN --lookup number v_sum_variable := getNumber (i_blah); --cal
FUNCTION getFooCursor (i_blah IN VARCHAR)
RETURN t_ref_cursor
IS
v_sum_variable NUMBER;
BEGIN
--lookup number
v_sum_variable := getNumber (i_blah);
--call function that raises NO_DATA_FOUND exception
doRaiseException();
--the exception handler is only supposed to catch for this block
BEGIN
--do stuff and end up with a cursor
RETURN barCursor(v_sum_variable);
EXCEPTION
WHEN OTHERS THEN
--set some variables
END
END;
PROCEDURE doRaiseException ()
IS
BEGIN
RAISE NO_DATA_FOUND;
END;
让我们假设doRaiseException()
如下所示:
FUNCTION getFooCursor (i_blah IN VARCHAR)
RETURN t_ref_cursor
IS
v_sum_variable NUMBER;
BEGIN
--lookup number
v_sum_variable := getNumber (i_blah);
--call function that raises NO_DATA_FOUND exception
doRaiseException();
--the exception handler is only supposed to catch for this block
BEGIN
--do stuff and end up with a cursor
RETURN barCursor(v_sum_variable);
EXCEPTION
WHEN OTHERS THEN
--set some variables
END
END;
PROCEDURE doRaiseException ()
IS
BEGIN
RAISE NO_DATA_FOUND;
END;
当我在TOAD中调试此函数时,它会很有帮助地通知我已引发NO_DATA_FOUND异常。但是,它会立即执行下一行(调用了barCursor()
),函数完成时就好像没有出错一样
我尝试过替换doRaiseException()代码>直接与生成未找到的数据代码>用于测试目的(它实际上做的不止这些),这会停止getFooCursor()
中的执行,但无论SQL如何再次调用它,都会完全忽略异常
这就是PL/SQL中异常的工作方式吗?它们不是像Java或C中那样冒泡吗?也许我遗漏了一些关于Oracle中异常的重要信息。我如何获得一个异常以向主机冒泡
这是我的Oracle版本(从v$version返回):
异常按照您的设想工作并“冒泡”,所以您一定在某个地方发现了它
这就是正在发生的事情。。。您正在捕获每个异常,这不是最佳实践。您可以确保只有自己定义了一个。然而,这似乎不是你想在这里做的。您只想重新引发一个异常
所以,你可以在你的子程序中提高它,然后在你的调用块中做类似的事情:
begin
RaiseException;
exception
when my_exception_package.my_exception then
raise;
when others then
DoSomethingElse;
end;
这样,您可以捕获要引发的异常,然后重新引发它们。如果异常情况不同,则继续当前的节目流程。您对异常情况的理解是正确的。然而,对于异常的工作方式来说,这是一个值得注意的例外:在SQL上下文中,找不到任何数据都会被默默地忽略。这是一个“特性”,因为Oracle就是这样告诉其他进程没有更多数据可读取的
对于自定义异常,您可能需要捕获未找到的数据,并将其作为不同的异常引发。这通常是一种处理异常的可怕方法,但这里没有好的替代方法
SQL> create or replace function function1 return number is
2 begin
3 raise no_data_found;
4 return 1;
5 end;
6 /
Function created.
SQL> select function1 from dual;
FUNCTION1
----------
1 row selected.
SQL> create or replace function function2 return number is
2 begin
3 raise no_data_found;
4 return 1;
5 exception when no_data_found then
6 raise_application_error(-20000, 'NO_DATA_FOUND raised');
7 end;
8 /
Function created.
SQL> select function2 from dual;
select function2 from dual
*
ERROR at line 1:
ORA-20000: NO_DATA_FOUND raised
ORA-06512: at "JHELLER.FUNCTION2", line 6
你确定你的第一个函数看起来就是这样吗?异常按照您的设想工作并“冒泡”,所以您一定在某个地方捕捉到了它。@Ben:我在我的示例中添加了一些信息,在阅读您的评论后,这些信息突然变得更加相关。回想起来很明显。。。