异常处理
错误处理
错误处理部分位于程序的可执行部分之后,是由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的雇员名字。
错误处理
错误处理部分位于程序的可执行部分之后,是由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的雇员名字。
- 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;
- 编号错误,没有找到相应雇员!
- PL/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;
- 发生系统错误!
- 错误代码:?1476
- 错误信息:ORA-01476: 除数为 0
- PL/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 在连接时提供了无效用户名或口令
- 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;
- 无法插入NULL值!
- PL/SQL 过程已成功完成。
- 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;
- 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;
- DECLARE
- *
- ERROR 位于第 1 行:
- ORA-20001: 编号小于7000的下限!
- ORA-06512: 在line 9