我们可以在异常中引发异常吗?

时间:2014-06-08 08:07:11

标签: oracle plsql

我们可以在异常中引发异常,例如RAISE my_exception异常中的WHEN OTHERS吗?

此外,我试图了解以下两种情况下的输出: (请注意,唯一的区别是异常的排序)

情景1

DECLARE
     lc_exception Exception;
     var1 number;
BEGIN
     select 1
     into var1
     from dual
     where 1=2;
EXCEPTION
     when lc_exception then
       dbms_output.put_line('This is my exception');

     when no_data_found then
       raise lc_exception;

     when others then
        dbms_output.put_line('There could be some other exception');
END;

场景2

DECLARE
     lc_exception Exception;
     var1 number;
BEGIN
     select 1
     into var1
     from dual
     where 1=2;
EXCEPTION
     when no_data_found then
       raise lc_exception; 

     when lc_exception then
       dbms_output.put_line('This is my exception');

     when others then
        dbms_output.put_line('There could be some other exception');
END;

2 个答案:

答案 0 :(得分:1)

两种情况都有类似的错误堆栈:

ORA-06510: PL/SQL: unhandled user-defined exception
ORA-06512: at line 20
ORA-01403: no data found

唯一的区别是提出用户定义的异常的确切位置(第20行与第18行)。

  1. select匹配没有行,因此Oracle no_data_found在错误堆栈中引发了ORA-01403: no data found
  2. 异常由块的异常处理程序块捕获。
  3. 在异常处理程序中,引发了用户定义的异常lc_exception
  4. 因为程序没有其他异常处理程序,所以用户定义的异常泄露给主机环境(在我的情况下是sqlplus客户端) - ORA-06510: PL/SQL: unhandled user-defined exception并且程序终止。
  5. 异常传播在两种情况下都类似,因为在这两种情况下都会引发相同的初始异常no_data_found,并且只有一个异常处理块。因此,no_data_foundlc_exception处理程序的顺序并不重要。

    有关异常处理/传播的更详细说明,请参阅:Oracle文档中的PL/SQL Error Handling

答案 1 :(得分:0)

您只需要一个异常处理程序来捕获您的本地异常。如果在异常处理程序中引发异常,则无法在同一个异常处理程序中捕获它。

DECLARE
  lc_exception EXCEPTION;
  var1 number;
BEGIN
  BEGIN
    SELECT 1
    INTO var1
    FROM dual
    WHERE 1=2;
  EXCEPTION -- this is where the exception will be raised
    WHEN no_data_found THEN 
      raise lc_exception;
  END;

  dbms_output.put_line( 'This will never be executed.' );

EXCEPTION -- this is where the exception will be caught
  WHEN lc_exception THEN
    dbms_output.put_line( 'This is my exception' );

  WHEN others THEN
    dbms_output.put_line( 'There could be some other exception' );
END;

但是,您可能需要考虑稍微不同的方法。

DECLARE
  lc_exception EXCEPTION;
  PRAGMA EXCEPTION_INIT( lc_exception, -20222 );
  var1 NUMBER;
BEGIN
  BEGIN
    SELECT 1
    INTO var1
    FROM dual
    WHERE 1=2;
  EXCEPTION
    WHEN NO_DATA_FOUND THEN 
    RAISE_APPLICATION_ERROR( -20222, 'This is my exception' );
  END;

  DBMS_OUTPUT.PUT_LINE( 'This will never be executed.' );

EXCEPTION
    WHEN lc_exception THEN
      DBMS_OUTPUT.PUT_LINE( SQLERRM );

    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE( 'Some other exception: ' || SQLERRM );
END;