3.7.3 非预定义异常

在PL/SQL中还有一类会经常遇到的错误。每个错误都有相应的错误代码和错误原因,但是由于Oracle没有为这样的错误定义一个名称,因而不能直接进行异常处理。在一般情况下,只能在PL/SQL块执行出错时查看其出错信息。

编写PL/SQL程序时,应该充分考虑到各种可能出现的异常,并且都作出适当的处理,这样的程序才是健壮的。对于这类非预定义的异常,由于它也被自动抛出的,因而只需要定义一个异常,把这个异常的名称与错误的代码关联起来,然后就可以像处理预定义异常那样处理这样的异常了。非预定义异常的处理过程如图3.3所示。

figure_0128_0025

图 3.3 非预定义异常的处理过程

异常的定义在PL/SQL块的声明部分进行,定义的格式为:


异常名称 EXCEPTION


其中异常名称是用户自己定义的一个名字,此时它仅仅是一个符号,没有任何意义。只有把这个名称与某个错误代码关联起来以后,这个异常才代表这个错误。把异常的名称与错误代码进行关联的格式是:


PRAGMA EXCEPTION_INIT(异常名,错误代码)


这种关联也是在PL/SQL块的声明部分进行。这样这个异常的名字就代表这个特定的错误了,当PL/SQL程序在执行的过程中发生这个错误时,这个异常将被自动抛出,这时就可以对其进行处理了。

例如,错误代码-02292的含义是违反了关联完整性。如果两个表通过主键和外键建立了关联关系,这时要从主表中删除一行,就可能会违反它们之间的关联完整性。例如员工表emp与部门表dept通过列deptno建立了关联关系,如果要从部门表dept删除一行,必须保证EMP表中没有这个部门的员工,否则就违反了它们之间的关联完整性。下面的代码演示了试图删除部门10的数据时发生的错误,因为在表emp中还有部门10的员工。


SQL>DELETE FROM dept WHERE deptno=10;

DELETE FROM dept WHERE deptno=10

*

ERROR位于第1行:

ORA-02292:违反完整约束条件(SCOTT.FK_DEPTNO)-已找到子记录日志


如果这时定义一个异常,把这个异常与错误代码-02292关联起来,就可以在PL/SQL块的异常处理部分对其进行处理了。下面是处理这个异常的代码。


DECLARE

reference_err EXCEPTION;

PRAGMA EXCEPTION_INIT(reference_err,-02292);

BEGIN

DELETE FROM dept WHERE deptno=10;

EXCEPTION

WHEN reference_err THEN

dbms_output.put_line('您所进行的操作违反了关联完整性');

END;


这个PL/SQL块的执行结果为:


您所进行的操作违反了关联完整性