PL/SQL:捕获编号异常?

Posted

技术标签:

【中文标题】PL/SQL:捕获编号异常?【英文标题】:PL/SQL: catching numbered exception? 【发布时间】:2016-01-30 00:52:17 【问题描述】:

这是捕获命名异常的规范方法。

  begin
      select ...;
  exception
  when zero_divide then
        ...
  end;

如何捕获编号异常?可以在一个when子句中指定多个异常条件吗?

ORA-01555: snapshot too old: ...
ORA-08180: no snapshot found based on specified time
ORA-01466: unable to read data - table definition has changed

【问题讨论】:

使用EXCEPTION_INIT Pragma,有关详细信息和示例,请参阅此链接:docs.oracle.com/cd/B19306_01/appdev.102/b14261/…。另请参阅此链接:docs.oracle.com/cd/B19306_01/appdev.102/b14261/errors.htm#i9355 以了解处理异常的基础知识。您可以指定多个异常处理程序,只需链接 WHEN .. THEN .. WHEN .. THEN.. 等。 【参考方案1】:

我想到的一种可能的方法是在其他处理程序和内部检查 sqlerrm(sqlcode) 时编写一个。

if (sqlerrm(sqlcode) = ORA-01555) then
do this
elsif ....

【讨论】:

它不会有ORA-01555的值,只有-1555的数值,据我记得docs.oracle.com/cd/B19306_01/appdev.102/b14261/…。 那是真的,,我的坏。 嗯.. 你的语法绝对不是 PL/SQL。但总的来说这个想法很好。 是的,过去 6 个月我一直在使用 Java 进行编码。我会牢记坚持plsql语法,下次尝试发布语法正确的逻辑。【参考方案2】:

首先,在documentation之后,我们必须说:

每个异常都可以通过PRAGMA EXCEPTION_INIT只有一个错误代码相关联, 并且同一异常的许多 pragma 声明不会获得编译错误,但最新的 pragma 会覆盖所有以前的 pragma。 所以我们没有自然的(或原生的)PL/SQL 方法来将多个异常代码联合到一个异常名称下以能够 用 WHEN my_unversal_exception THEN 捕捉它们。

所以当我们想一次捕获许多异常时,没有其他选择,只能进入WHEN OTHERS THEN部分并执行一些技巧(仅限于想象力)。这已经不是什么秘密了——我们必须处理sqlcode 函数,所以让我们把它做得漂亮并尝试封装这些东西。

可能的解决方案之一: 创建布尔函数,用于检查错误代码(可能还有错误消息),并将它们用作CASE TRUE WHEN ... 中的守卫。

CREATE OR REPLACE PACKAGE exc_filter IS 
  FUNCTION exception_kind_A RETURN boolean;
  FUNCTION exception_kind_B RETURN boolean;
  FUNCTION exception_kind_C RETURN boolean;
END;
/

CREATE OR REPLACE PACKAGE BODY exc_filter IS  

  -- I use negation of sqlcode to reduce noice of minuses.

  FUNCTION exception_kind_A RETURN boolean is BEGIN
    RETURN -sqlcode IN (01476, 06502);
  END;

  FUNCTION exception_kind_B RETURN boolean IS BEGIN
    RETURN -sqlcode BETWEEN 20010 AND 20020;
  END;

  -- a bit of discouraging flexibility
  FUNCTION exception_kind_C RETURN boolean IS BEGIN
    RETURN instr(sqlerrm, 'Yay') > 0;
  END;
END;
/

DECLARE
  x number; 
BEGIN
   -- each line raises an error - uncomment to try

   x := 5/0;

   -- raise_application_error(-20008, 'Yay');

   -- raise_application_error(-20015, 'Another');

   -- x := to_number('abc');

EXCEPTION WHEN OTHERS THEN -- catch all, then switch
  CASE TRUE
  WHEN exc_filter.exception_kind_A THEN dbms_output.put_line('Kind A : ' || sqlerrm);
  WHEN exc_filter.exception_kind_B THEN dbms_output.put_line('Kind B : ' || sqlerrm);
  WHEN exc_filter.exception_kind_C THEN dbms_output.put_line('Kind C : ' || sqlerrm);
  ELSE raise; -- strongly recommended line
  END CASE; 
END;
/

【讨论】:

以上是关于PL/SQL:捕获编号异常?的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL value_error 异常没有被捕获

Oracle PL/SQL - 如何在异常子句的单独表中捕获坏数据?

Oracle PL/SQL 在循环中捕获锁定异常并继续

匿名 PL/SQL 块检查异常

PL/SQL系统定义的异常操作实例讲解

PL/SQL 异常块不工作