Oracle中的异常可以分为哪几类?
♣ 答案部分
异常(EXCEPTION)处理是用来处理正常执行过程中未预料到的事件,包括程序块的异常处理、预定义的错误和自定义错误。如果PL/SQL程序块一旦产生异常,而程序并没有指出如何处理,那么程序就会自动终止运行。
异常处理部分一般放在PL/SQL程序体的后半部分,结构如下所示:
EXCEPTION
WHEN first_exception THEN <code to handle first exception >
WHEN second_exception THEN <code to handle second exception >
WHEN OTHERS THEN <code to handle OTHERS exception >
对于异常处理,需要注意以下几点内容:
(1)异常处理可以按任意次序排列,但OTHERS必须放在最后。
(2)当程序出现异常时,程序立即暂停工作,跳转到EXCEPTION部分。使用WHEN … THEN来处理系统定义的异常。使用WHEN OTHERS THEN处理未定义的异常。
(3)当异常处理结束后,Oracle就将处理权交给调用者。结束PL/SQL块的运行。
Oracle将异常分为预定义异常、非预定义异常和自定义异常三种。
1、预定义异常(Predefined)
当PL/SQL应用程序违反了Oracle规定的限制时,就会隐含地触发一个内部异常,这就是预定义异常。预定义异常用于处理常见的Oracle错误,对这种异常情况的处理,无需在程序中定义,由Oracle自动将其触发。它们全部放在PL/SQL自带的标准包中,这样程序员就无需再次定义了。预定义异常大约有20多个,下表是一些常见的预定义异常:
表 5-3 Oracle预定义异常
错误号
异常错误信息名称
说明
ORA-01403
NO_DATA_FOUND
SELECT INTO没有找到数据
ORA-01422
TOO_MANY_ROWS
SELECT INTO返回多行
8000 ORA-06501
PROGRAM_ERROR
内部错误,需重新安装数据字典视图和PL/SQL包
ORA-06511
CURSOR_ALREADY_OPEN
试图打开一个已存在的游标
ORA-06530
ACCESS_INTO_NULL
试图为NULL对象的属性赋值
ORA-01012
NOT_LOGGED_ON
没有连接到Oracle
ORA-01001
INVALID_CURSOR
试图使用一个无效的游标
ORA-00061
TRANSACTION_BACKED_OUT
由于发生死锁事务被撤消
ORA-00051
TIMEOUT_ON_RESOURCE
在等待资源时发生超时
ORA-00001
DUP_VAL_ON_INDEX
试图破坏一个唯一性限制
ORA-01017
LOGIN_DENIED
无效的用户名/口令
ORA-01476
ZERO_DIVIDE
试图被零除
ORA-01722
INVALID_NUMBER
转换一个数字失败
ORA-06500
STORAGE_ERROR
内存不够或内存被破坏触发的内部错误
ORA-06502
VALUE_ERROR
赋值操作,变量长度不足,触发该异常
ORA-06504
ROWTYPE_MISMATCH
宿主游标变量与PL/SQL变量有不兼容行类型
ORA-06531
COLLECTION_IS_NULL
试图给没有初始化的嵌套表变量或者VARRY变量赋值
ORA-06532
SUBSCRIPT_OUTSIDE_LIMIT
对嵌套或VARRAY索引使用了负数
ORA-06533
SUBSCRIPT_BEYOND_COUNT
对嵌套或VARRAY索引的引用大于集合中元素的个数
预定义异常的示例如下所示:
SYS@lhrdb> SET SERVEROUTPUT ON
SYS@lhrdb> DECLARE
2 V_ENAME SCOTT.EMP.ENAME%TYPE;
3 V_SAL SCOTT.EMP.SAL%TYPE;
4 V_INPUT SCOTT.EMP.SAL%TYPE := 100;
5 BEGIN
6 SELECT ENAME, SAL INTO V_ENAME, V_SAL FROM SCOTT.EMP WHERE SAL = V_INPUT;
7 DBMS_OUTPUT.PUT_LINE(V_ENAME || ',' || V_SAL);
8 EXCEPTION
9 WHEN NO_DATA_FOUND THEN
10 DBMS_OUTPUT.PUT_LINE('没找到任何数据');
11 WHEN TOO_MANY_ROWS THEN
12 DBMS_OUTPUT.PUT_LINE('找到多行数据,建议使用游标');
13 WHEN OTHERS THEN
14 DBMS_OUTPUT.PUT_LINE('出错了!!');
15 DBMS_OUTPUT.PUT_LINE(SQLCODE || ',' || SQLERRM);
16
17 END;
18 /
没找到任何数据
PL/SQL procedure successfully completed.
2、非预定义异常(Non Predefined)
非预定义异常用于处理预定义异常不能处理的异常,即其它标准的Oracle错误。使用预定义异常只能处理系统预定义的20多个Oracle错误,而当使用PL/SQL开发应用程序时,可能会遇到其它的一些Oracle错误。例如,在PL/SQL块中执行DML语句时,违反了约束规定等等。在这样的情况下,就可以使用非预定义异常来处理。
Oracle提供了2个函数SQLCODE和SQLERRM用于返回错误信息:
l SQLCODE:返回错误代码
l SQLERRM:返回与错误代码关联的消息
这样就可以在错误日志表中记录程序在执行过程中发生的错误信息了。
非预定义异常的示例如下所示:
SYS@lhrdb> SET SERVEROUTPUT ON
SYS@lhrdb> DECLARE
2 FK_EXCEPTION EXCEPTION; --定义一个异常类型的变量
3 PRAGMA EXCEPTION_INIT(FK_EXCEPTION, -2292); --将该变量和指定的错误码绑定
4 V_ERROR_CODE NUMBER;
5 V_ERROR_MESSAGE VARCHAR2(255);
6 BEGIN
7 DELETE FROM SCOTT.DEPT WHERE DEPTNO = 20;
8 EXCEPTION
9 WHEN FK_EXCEPTION THEN
10 --可以用异常类型的名字进行异常的捕获
11 DBMS_OUTPUT.PUT_LINE('找到子记录,删除失败');
12 WHEN OTHERS THEN
13 ROLLBACK;
14 DBMS_OUTPUT.PUT_LINE(SQLCODE || ',' || SQLERRM);
15 END;
16 /
找到子记录,删除失败
PL/SQL procedure successfully completed.
3、自定义异常(User_define)
自定义异常用于处理与Oracle错误无关的其它情况。对这种异常情况的处理,需要用户在程序中定义,然后显式地在程序中将其触发。
预定义异常和自定义异常都是与Oracle错误相关的,并且出现的Oracle错误会隐含地触发相应的异常;而自定义异常与Oracle错误没有任何关联,它是由开发人员为特定情况所定义的异常。当与一个异常相关的错误出现时,就会隐含触发该异常。用户定义异常是通过显式使用RAISE语句来触发。当触发一个异常时,控制程序就转到异常块部分,执行错误处理代码。
自定义异常的示例如下所示:
SYS@lhrdb> SET SERVEROUTPUT ON
SYS@lhrdb> DECLARE
2 V_SAL SCOTT.EMP.SAL%TYPE;
3 V_ENAME SCOTT.EMP.ENAME%TYPE;
4 V_EMPNO SCOTT.EMP.EMPNO%TYPE := 6;
5 SALARY_EXCEPTION EXCEPTION; --定义异常的类型(名字)
6 BEGIN
7 SELECT ENAME, SAL INTO V_ENAME, V_SAL FROM SCOTT.EMP WHERE EMPNO = V_EMPNO;
8 IF V_SAL < 1500 THEN
9 V_SAL := V_SAL + 100;
10 DBMS_OUTPUT.PUT_LINE(V_ENAME || '涨工资后:' || V_SAL);
11 ELSE
12 RAISE SALARY_EXCEPTION; --抛出自定义的异常
13 END IF;
14 EXCEPTION
15 WHEN SALARY_EXCEPTION THEN
16 --捕获自定义的异常
17 DBMS_OUTPUT.PUT_LINE('薪金没有达到最低水平,不需要涨工资');
18 WHEN NO_DATA_FOUND THEN
19 DBMS_OUTPUT.PUT_LINE('没有找到' || V_EMPNO || '编码的员工');
20 WHEN OTHERS THEN
21 DBMS_OUTPUT.PUT_LINE(SQLCODE || ',' || SQLERRM);
22 END;
23 /
没有找到6编码的员工
PL/SQL procedure successfully completed.
---------------优质麦课------------
详细内容可以添加麦老师微信或QQ私聊。
● 本文作者:小麦苗,只专注于数据库的技术,更注重技术的运用
● 作者博客地址:http://blog.itpub.net/26736162/abstract/1/
● 本系列题目来源于作者的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解
● 版权所有,欢迎分享本文,转载请保留出处
● QQ:646634621 QQ群:618766405
● 题目解答若有不当之处,还望各位朋友批评指正,共同进步
长按下图识别二维码或微信扫描下图二维码来关注小麦苗的微信公众号:xiaomaimiaolhr,学习最实用的数据库技术。
本文分享自微信公众号 - DB宝(lhrdba)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。