【问题标题】:Is it a bad practice to use global exceptions in PL/SQL?在 PL/SQL 中使用全局异常是一种不好的做法吗?
【发布时间】:2010-12-29 10:28:47
【问题描述】:

执行下面的代码是一种不好的做法吗?写了会不会有什么不好的事情发生?

编辑:这只是一个例子。我不会将 dbms_output 用于任何真正的错误报告。

CREATE OR REPLACE PACKAGE my_package
AS
PROCEDURE master;
END;
/

CREATE OR REPLACE PACKAGE BODY my_package
AS

my_global_interrupt EXCEPTION;


PROCEDURE my_private_procedure
IS
BEGIN
  -- in case some flag is raised, raise exception to stop process and prepare for resume
  RAISE my_global_interrupt;
END;

PROCEDURE master
IS
BEGIN
  my_private_procedure;
EXCEPTION
  WHEN my_global_interrupt THEN 
    dbms_output.put_line('global interrupt, ');
    -- prepare to resume
END;

END;
/

【问题讨论】:

    标签: oracle exception plsql


    【解决方案1】:

    相反,全局定义的用户例外是一种很好的做法。考虑以下包体的骨架。

    create or replace package body my_pkg 
    as
        my_x1 exception;
        my_x2 exception;
        my_x3 exception;
        PROCEDURE p1 is
        begin
            ...
        exception
            when no_data_found then raise my_x1;
        end p1;
        PROCEDURE p2 is
        begin
            ...
        exception
            when no_data_found then raise my_x2;
        end p2;
        PROCEDURE p3 is
        begin
            ...
        exception
            when no_data_found then raise my_x3;
        end p3;
        PROCEDURE master is
        begin
            p1;
            p2;
            p3;
        exception
            when my_x1 then do_this;
            when my_x2 then do_that;
            when my_x3 then do_the_other;
        end master;
    end my_pkg;
    /
    

    使用全局声明的异常使master 过程中的异常处理更容易。

    另外,请记住,有时我们希望将异常传播到包之外,例如调用我们公开声明的过程的程序。我们可以通过在包规范中定义我们的异常来做到这一点。这意味着其他程序可以引用它们...

    SQL> begin
      2      my_pkg.master;
      3  exception
      4      when my_pkg.my_public_x1
      5          then dbms_output.put_line('oh no!');
      6  end;
      7  /
    oh no!
    
    PL/SQL procedure successfully completed.
    
    SQL>
    

    我们还可以将此类异常与特定的错误编号相关联,以便即使调用过程没有明确处理它们也可以识别它们。

    SQL> exec my_pkg.master
    BEGIN my_pkg.master; END;
    
    *
    ERROR at line 1:
    ORA-20999:
    ORA-06512: at "APC.MY_PKG", line 32
    ORA-06512: at line 1
    
    
    SQL>
    

    这比一般的 ORA-06510 错误(稍微)更有帮助。

    【讨论】:

    • 您需要小心 RAISE my_x#。它丢失了发生原始错误的行号。这会使调试更加困难。您可以使用:DBMS_UTILITY.FORMAT_ERROR_BACKTRACE。
    • 公平点。像很多事情一样,总是有警告和扩展,在你知道之前,你已经在通往 OPP5 oreilly.com/catalog/9780596514464 (1232pp) 的路上了。但显然日志记录和其他内容是错误处理的重要组成部分,应该在级联异常之前在错误点完成。
    【解决方案2】:

    对我来说看起来很合理,前提是您很高兴在中断条件之后可以恢复处理。如果您打算以某种方式记录中断,最好使用自治事务将一行插入日志表。在整个过程完成之前,您不会从 DBMS_OUTPUT 中看到任何内容。然后您将立即看到所有 DBMS_OUTPUT。

    【讨论】:

      猜你喜欢
      • 2012-10-12
      • 2017-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多