子程序中的异常后,函数恢复执行

时间:2013-05-15 15:01:08

标签: 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);

    --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;

让我们说doRaiseException()看起来像这样:

PROCEDURE doRaiseException ()
IS
BEGIN
    RAISE NO_DATA_FOUND;
END;

当我在TOAD中调试此函数时,它有助于通知我已经引发了NO_DATA_FOUND异常。然而,它然后立即继续执行下一行(调用barCursor())并且函数完成,好像什么都没有出错。

我尝试直接用doRaiseException();替换RAISE NO_DATA_FOUND;用于测试目的(它实际上做的不止于此)并且这会在getFooCursor()内停止执行,但无论SQL再次调用它都会完全忽略异常

这是PL / SQL中异常的工作原理吗?他们不像在Java或C#中那样冒泡吗?也许我错过了一些关于Oracle异常的重要信息。如何获得一个例外以冒泡到主机?


这是我的Oracle版本(从v $版本返回):

Oracle Database 10g Enterprise Edition Release 10.2.0.5.0 - 64bi
PL/SQL Release 10.2.0.5.0 - Production                          
CORE    10.2.0.5.0  Production                                      
TNS for HPUX: Version 10.2.0.5.0 - Production                   
NLSRTL Version 10.2.0.5.0 - Production

2 个答案:

答案 0 :(得分:2)

您对异常的理解是正确的。但是,这是异常如何工作的一个值得注意的例外:在SQL上下文中忽略NO_DATA_FOUND。这是一个“功能”,因为这就是Oracle告诉其他进程不再需要读取数据的方式。

对于自定义异常,您可能需要捕获NO_DATA_FOUND并将其作为不同的异常引发。这通常是一种处理异常的可怕方式,但这里没有好的选择。

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

答案 1 :(得分:1)

例外工作正如你想象的那样“冒泡”,所以你必须在某个地方捕捉它。

这就是正在发生的事情......你正在捕捉每个异常,这不是最好的做法。如果您自己定义一个,则可以仅确保catch a specific exception。但是,这似乎不是你想要做的。您只想重新引发单个例外。

所以,你可以define a custom exception in a separate package,在你的子程序中提高它,然后在你的调用块中做这样的事情:

begin
   RaiseException;

exception
   when my_exception_package.my_exception then
      raise;
   when others then
      DoSomethingElse;
end;

通过这种方式,您可以捕获要提升的异常,然后重新提升它们。如果异常不同,那么继续当前的程序流程。