首页  ·  知识 ·  数据库
异常处理与错误处理
网友    Oracle  编辑:dezai   图片来源:网络
异常处理与错误处理

异常处理
错误处理
错误处理部分位于程序的可执行部分之后,是由WHEN语句引导的多个分支构成的。错误处理的语法如下:
EXCEPTION
WHEN 错误1[OR 错误2] THEN
语句序列1;
WHEN 错误3[OR 错误4] THEN
语句序列2;
WHEN OTHERS
语句序列n;
END;
其中:
错误是在标准包中由系统预定义的标准错误,或是由用户在程序的说明部分自定义的错误,参见下一节系统预定义的错误类型。
语句序列就是不同分支的错误处理部分。
凡是出现在WHEN后面的错误都是可以捕捉到的错误,其他未被捕捉到的错误,将在WHEN OTHERS部分进行统一处理,OTHENS必须是EXCEPTION部分的最后一个错误处理分支。如要在该分支中进一步判断错误种类,可以通过使用预定义函数SQLCODE( )和SQLERRM( )来获得系统错误号和错误信息。
如果在程序的子块中发生了错误,但子块没有错误处理部分,则错误会传递到主程序中。
下面是由于查询编号错误而引起系统预定义异常的例子。
【训练1】  查询编号为1234的雇员名字。
Sql代码 
SET SERVEROUTPUT ON 
DECLARE 
v_name VARCHAR2(10);  
BEGIN 
   SELECT   ename  
   INTO     v_name  
   FROM     emp  
   WHERE    empno = 1234;  
DBMS_OUTPUT.PUT_LINE('该雇员名字为:'|| v_name);  
EXCEPTION  
  WHEN NO_DATA_FOUND THEN 
    DBMS_OUTPUT.PUT_LINE('编号错误,没有找到相应雇员!');  
  WHEN OTHERS THEN 
    DBMS_OUTPUT.PUT_LINE('发生其他错误!');  
END; 
执行结果为:
Sql代码 
编号错误,没有找到相应雇员!  
        PL/SQL 过程已成功完成。 
说明:在以上查询中,因为编号为1234的雇员不存在,所以将发生类型为“NO_DATA_
FOUND”的异常。“NO_DATA_FOUND”是系统预定义的错误类型,EXCEPTION部分下的WHEN语句将捕捉到该异常,并执行相应代码部分。在本例中,输出用户自定义的错误信息“编号错误,没有找到相应雇员!”。如果发生其他类型的错误,将执行OTHERS条件下的代码部分,显示“发生其他错误!”。
【训练2】  由程序代码显示系统错误。
Sql代码 
SET SERVEROUTPUT ON 
DECLARE 
v_temp NUMBER(5):=1;  
BEGIN 
v_temp:=v_temp/0;  
EXCEPTION  
  WHEN OTHERS THEN 
DBMS_OUTPUT.PUT_LINE('发生系统错误!');  
    DBMS_OUTPUT.PUT_LINE('错误代码:'|| SQLCODE( ));  
    DBMS_OUTPUT.PUT_LINE('错误信息:' ||SQLERRM( ));  
        END; 
执行结果为:
Sql代码 
发生系统错误!  
        错误代码:?1476  
        错误信息:ORA-01476: 除数为 0  
        PL/SQL 过程已成功完成。 
说明:程序运行中发生除零错误,由WHEN OTHERS捕捉到,执行用户自己的输出语句显示错误信息,然后正常结束。在错误处理部分使用了预定义函数SQLCODE( )和SQLERRM( )来进一步获得错误的代码和种类信息。
预定义错误
Oracle的系统错误很多,但只有一部分常见错误在标准包中予以定义。定义的错误可以在EXCEPTION部分通过标准的错误名来进行判断,并进行异常处理。常见的系统预定义异常如下所示。
Sql代码 
错 误 名 称 错误代码    错 误 含 义  
CURSOR_ALREADY_OPEN ORA_06511   试图打开已经打开的游标  
INVALID_CURSOR  ORA_01001   试图使用没有打开的游标  
DUP_VAL_ON_INDEX    ORA_00001   保存重复值到惟一索引约束的列中  
ZERO_DIVIDE ORA_01476   发生除数为零的除法错误  
INVALID_NUMBER  ORA_01722   试图对无效字符进行数值转换  
ROWTYPE_MISMATCH    ORA_06504   主变量和游标的类型不兼容  
VALUE_ERROR ORA_06502   转换、截断或算术运算发生错误  
TOO_MANY_ROWS   ORA_01422   SELECT…INTO…语句返回多于一行的数据  
NO_DATA_FOUND   ORA_01403   SELECT…INTO…语句没有数据返回  
TIMEOUT_ON_RESOURCE ORA_00051   等待资源时发生超时错误  
TRANSACTION_BACKED_OUT  ORA_00060   由于死锁,提交失败  
STORAGE_ERROR   ORA_06500   发生内存错误  
PROGRAM_ERROR   ORA_06501   发生PL/SQL内部错误  
NOT_LOGGED_ON   ORA_01012   试图操作未连接的数据库  
LOGIN_DENIED    ORA_01017   在连接时提供了无效用户名或口令 
比如,如果程序向表的主键列插入重复值,则将发生DUP_VAL_ON_INDEX错误。
如果一个系统错误没有在标准包中定义,则需要在说明部分定义,语法如下:
错误名 EXCEPTION;
定义后使用PRAGMA EXCEPTION_INIT来将一个定义的错误同一个特别的Oracle错误代码相关联,就可以同系统预定义的错误一样使用了。语法如下:
PRAGMA EXCEPTION_INIT(错误名,- 错误代码);
【训练1】  定义新的系统错误类型。
Sql代码 
SET SERVEROUTPUT ON 
        DECLARE 
        V_ENAME VARCHAR2(10);  
        NULL_INSERT_ERROR EXCEPTION;  
        PRAGMA EXCEPTION_INIT(NULL_INSERT_ERROR,-1400);  
        BEGIN 
        INSERT INTO EMP(EMPNO) VALUES(NULL);  
EXCEPTION  
WHEN NULL_INSERT_ERROR THEN 
    DBMS_OUTPUT.PUT_LINE('无法插入NULL值!');  
  WHEN OTHERS  THEN 
    DBMS_OUTPUT.PUT_LINE('发生其他系统错误!');  
END; 
执行结果为:
Sql代码 
无法插入NULL值!  
        PL/SQL 过程已成功完成。 
  说明:NULL_INSERT_ERROR是自定义异常,同系统错误1400相关联。
自定义异常
程序设计者可以利用引发异常的机制来进行程序设计,自己定义异常类型。可以在声明部分定义新的异常类型,定义的语法是:
错误名 EXCEPTION;
用户定义的错误不能由系统来触发,必须由程序显式地触发,触发的语法是:
RAISE 错误名;
RAISE也可以用来引发模拟系统错误,比如,RAISE ZERO_DIVIDE将引发模拟的除零错误。
使用RAISE_APPLICATION_ERROR函数也可以引发异常。该函数要传递两个参数,第一个是用户自定义的错误编号,第二个参数是用户自定义的错误信息。使用该函数引发的异常的编号应该在20 000和20 999之间选择。
自定义异常处理错误的方式同前。
【训练1】  插入新雇员,限定插入雇员的编号在7000~8000之间。
Java代码 
SET SERVEROUTPUT ON  
DECLARE  
new_no NUMBER(10);  
new_excp1 EXCEPTION;  
new_excp2 EXCEPTION;  
BEGIN  
new_no:=6789;  
INSERT INTO emp(empno,ename)  
  VALUES(new_no, '小郑');  
  IF new_no<7000 THEN  
    RAISE new_excp1;  
  END IF;  
  IF new_no>8000 THEN  
    RAISE new_excp2;  
  END IF;  
  COMMIT;  
EXCEPTION  
WHEN new_excp1  THEN  
    ROLLBACK;  
    DBMS_OUTPUT.PUT_LINE('雇员编号小于7000的下限!');  
    WHEN new_excp2  THEN  
    ROLLBACK;  
    DBMS_OUTPUT.PUT_LINE('雇员编号超过8000的上限!');  
    END; 
执行结果为:
雇员编号小于7000的下限!
PL/SQL 过程已成功完成。
说明:在此例中,自定义了两个异常:new_excp1和new_excp2,分别代表编号小于7000和编号大于8000的错误。在程序中通过判断编号大小,产生对应的异常,并在异常处理部分回退插入操作,然后显示相应的错误信息。
【训练2】  使用RAISE_APPLICATION_ERROR函数引发系统异常。
Sql代码 
SET SERVEROUTPUT ON 
DECLARE 
New_no NUMBER(10);  
BEGIN 
  New_no:=6789;  
INSERT INTO    emp(empno,ename)  
  VALUES(new_no, 'JAMES');  
IF new_no<7000 THEN 
    ROLLBACK;  
    RAISE_APPLICATION_ERROR(-20001, '编号小于7000的下限!');  
  END IF;  
  IF new_no>8000 THEN 
    ROLLBACK;  
    RAISE_APPLICATION_ERROR (-20002, '编号大于8000的下限!');  
  END IF;  
END; 
执行结果为:
Sql代码 
DECLARE 
        *  
        ERROR 位于第 1 行:  
        ORA-20001: 编号小于7000的下限!  
        ORA-06512: 在line 9 
  说明:在本训练中,使用RAISE_APPLICATION_ERROR引发自定义异常,并以系统错误的方式进行显示。错误编号为20001和20002。
注意:同上一个训练比较,此种方法不需要事先定义异常,可直接引发。
可以参考下面的程序片断将出错信息记录到表中,其中,errors为记录错误信息的表,SQLCODE为发生异常的错误编号,SQLERRM为发生异常的错误信息。
DECLARE
  v_error_code      NUMBER;
  v_error_message   VARCHAR2(255);
BEGIN
...
EXCEPTION
...
WHEN OTHERS THEN
    v_error_code := SQLCODE ;
    v_error_message := SQLERRM ;
    INSERT INTO errors
    VALUES(v_error_code, v_error_message);
END;

本文作者:网友 来源:网络
CIO之家 www.ciozj.com 微信公众号:imciow
    >>频道首页  >>网站首页   纠错  >>投诉
版权声明:CIO之家尊重行业规范,每篇文章都注明有明确的作者和来源;CIO之家的原创文章,请转载时务必注明文章作者和来源;
延伸阅读
也许感兴趣的
我们推荐的
主题最新
看看其它的