目录
一、预定义异常
由PL/SQL所提供的系统异常,Oracle提供了20多个预定义异常,每个预定义异常对应一个特定的Oracle错误,当PL/SQL块出现了这些Oracle错误时,会隐含地触发这些预定义异常。对于预定义异常情况的处理,无需在程序中定义,只需在PL/SQL块的异常处理部分,直接引用相应的异常情况名,并对其完成相应的异常错误处理即可。
预定义异常列表:
错误号 |
异常错误信息名称 |
说明 |
ORA-00001 |
DUP_VAL_ON_INDEX |
试图破坏一个唯一性限制 |
ORA-00051 |
TIMEOUT_ON_RESOURCE |
在等待资源时发生超时 |
ORA-01001 |
INVALID_CURSOR |
试图使用一个无效的游标 |
ORA-01012 |
NOT_LOGGED_ON |
没有连接到ORACLE |
ORA-01017 |
LOGIN_DENIED |
无效的用户名及口令 |
ORA-01403 |
NO_DATA_FOUND |
SELECT INTO没有找到数据 |
ORA-01422 |
TWO_MANY_ROWS |
SELECT INTO 返回多行 |
ORA-01410 |
SYS_INVALID_ROWID |
从字符串向ROWID转换发生错误 |
ORA-01476 |
ZERO_DIVIDE |
数字值除零时触发的异常 |
ORA-01722 |
INVALID_NUMBER |
转换一个数字失败 |
ORA-06500 |
STORAGE_ERROR |
内存不够引发的内部错误 |
ORA-06501 |
PROGRAM_ERROR |
存在PL/SQL内部问题 |
ORA-06502 |
VALUE_ERROR |
转换或截断错误 |
ORA-06504 |
ROWTYPE_MISMATCH |
宿主游标变量与 PL/SQL 游标变量的返回类型不兼容
|
ORA-06511 |
CURSOR_ALREADY_OPEN |
游标已经打开 |
ORA-06530 |
ACCESS_INTO_NULL |
未定义对象 |
ORA-06531 |
COLLECTION_IS_NULL |
集合元素未初始化 |
ORA-06532 |
SUBSCRIPT_OUTSIDE_LIMIT |
使用嵌套表或 VARRAY 时,将下标指定为负数
|
ORA-06533 |
SUBSCRIPT_BEYOND_COUNT |
元素下标超过嵌套表或 VARRAY 的最大值
|
ORA-06592 |
CASE_NOT_FOUND |
CASE 中若未包含相应的 WHEN ,并且没有设置 |
ORA-30625 |
SELF_IS_NULL |
使用对象类型时,在 null 对象上调用对象方法 |
--预定义异常处理
DECLARE
v_name emp.ename%TYPE;
v_sal emp.sal%TYPE:=&salary;
BEGIN
SELECT ename INTO v_name FROM emp WHERE sal = v_sal;
DBMS_OUTPUT.put_line(v_name||'的工资是:'||v_sal);
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.put_line('没有该工资的员工');
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.put_line('多个员工具有该工资');
WHEN OTHERS THEN
DBMS_OUTPUT.put_line('其他异常');
END;
SELECT * FROM EMP;
--800, 一个员工
--1250 多个员工
--8000 0个员工
二、非预定义异常处理
用于处理预定义异常所不能处理的Oracle错误。此种异常需要在程序中定义。
--获取异常的错误代码和错误信息
BEGIN
DELETE FROM DEPT WHERE deptno = &deptno;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.put_line(SQLCODE||'####'||SQLERRM);
END;
--非预定义异常的处理
DECLARE
--1:定义非预定义异常的标识符
e_fk EXCEPTION;
--2:将定义好的异常与Oracle错误建立关联
-- -2292错误代码
PRAGMA EXCEPTION_INIT(e_fk,-2292);
BEGIN
DELETE FROM DEPT WHERE deptno = &deptno;
EXCEPTION
--3:捕获并处理异常
WHEN e_fk THEN
DBMS_OUTPUT.PUT_LINE('此部门下有员工,不能删除此部门!');
WHEN OTHERS THEN
DBMS_OUTPUT.put_line(SQLCODE||'####'||SQLERRM);
END;
三、用户自定义的异常处理
如果你想在某个特定事件发生时向应用程序的用户发出一些警告信息,而事件本身不会抛出Oracle内部异常,这个异常是属于引用程序的特定异常。那么就需要自定义异常。用户定义的异常错误是通过显示使用RAISE语句来触发,当引发一个异常错误时,控制就转向到EXCEPTION块异常错误部分,执行错误处理代码。
--自定义异常
DECLARE
v_empno emp.empno%TYPE:=&empno;
--1:定义异常
e_no_result EXCEPTION;
BEGIN
UPDATE emp SET sal = sal + 100 WHERE empno = v_empno;
IF SQL%NOTFOUND THEN
--2:指定触发异常的时机
RAISE e_no_result;
ELSE
COMMIT;
END IF;
EXCEPTION
--3:捕捉并处理异常
WHEN e_no_result THEN
DBMS_OUTPUT.put_line('数据更新失败!');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('其他错误');
END;
四、在PLSQL中使用SQLCODE、SQLERRM
异常处理函数:
- 异常处理函数用于取得Oracle错误号和错误信息,其中函数SQLCODE用于取得错误号,SQLERRM用于取得错误信息。
- 当编写PL/SQL块时,通过在异常处理部分引用函数SQLCODE和SQLERRM,可以取得未预计到的Oracle错误。
- 通过使用内置过程RAISE_APPLICATION_ERROR,可以在建立子程序(过程、函数、包)时自定义错误号和错误信息。
--异常处理函数SQLCODE和SQLERRM的使用
DECLARE
v_empno emp.empno%TYPE:= &empno;
v_ename emp.ename%TYPE:= '&ename';
v_deptno emp.deptno%TYPE:= &deptno;
BEGIN
INSERT INTO emp(empno,ename,deptno)VALUES(v_empno,v_ename,v_deptno);
IF SQL%FOUND THEN
DBMS_OUTPUT.put_line('数据插入成功!');
COMMIT;
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.put_line('错误号:'||SQLCODE);
DBMS_OUTPUT.put_line('错误信息:'||SQLERRM);
END;