在PL / SQL中使用全局异常是不好的做法吗?

时间:2009-12-23 09:57:18

标签: oracle exception plsql

执行以下代码的操作是不好的做法?我写这篇文章会不会发生坏事?

编辑:这只是一个例子。我不会将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;
/

2 个答案:

答案 0 :(得分:8)

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

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过程中的异常处理更容易。

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

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错误(稍微)更有帮助。

答案 1 :(得分:2)

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