PLSQL中的例外处理
PLSQL中的例外一般有两种:
1、Oracle 内部错误抛出的例外:这又分为预定义例外(有错误号+常量定义)和 非预定义例外 (仅有错误号,无常量定义)
2、程序员显式的抛出的例外
1、内部错误抛出的例外
A.预定义例外(有错误号+常量定义)
B.非预定义例外(仅有错误号,无常量定义)
2、显式的抛出的例外
3、PLSQL中的例外处理的一般语法
EXCEPTION
WHEN exception1 [OR exception2 . . .] THEN
statement1;
statement2;
. . .
[WHEN exception3 [OR exception4 . . .] THEN
statement1;
statement2;
. . .]
[WHEN OTHERS THEN
statement1;
statement2;
. . .]
A.PLSQL定义的常见例外
Oracle 预定义好的常见例外:
–NO_DATA_FOUND
–TOO_MANY_ROWS
–INVALID_CURSOR
–ZERO_DIVIDE
–DUP_VAL_ON_INDEX
处理预定义的例外:有些常见例外,Oracle 都已经预定义好了,使用时无需预先声明,比如: NO_DATA_FOUND 和 TOO_MANY_ROWS 是最常见的例外
BEGIN
. . .
EXCEPTION
WHEN NO_DATA_FOUND THEN
statement1;
WHEN TOO_MANY_ROWS THEN
statement1;
WHEN OTHERS THEN
statement1;
statement2;
END;
B.OTHERS的处理
Others表明程序员未能预计到这种错误,所以全部归入到others 里面去了
4、Oracle 错误号和错误描述
Oracle 提供了两个内置函数 SQLCODE 和 SQLERRM 分别用来返回Oracle 错误号和错误描述
DECLARE
v_error_code NUMBER;
v_error_message VARCHAR2(255);
BEGIN
...
EXCEPTION
...
WHEN OTHERS THEN
ROLLBACK;
v_error_code := SQLCODE ;
v_error_message := SQLERRM ;
INSERT INTO errors
VALUES(v_error_code, v_error_message);
END;
5、处理非预定义的Oracle错误
此类错误属于Oracle错误,有编号,但无错误名称定义,使用时需要先声明,并 进行错误初始化
DEFINE p_deptno = 10
DECLARE
e_emps_remaining EXCEPTION;
PRAGMA EXCEPTION_INIT
(e_emps_remaining, -2292);
BEGIN
DELETE FROM departments
WHERE department_id = &p_deptno;
COMMIT;
EXCEPTION
WHEN e_emps_remaining THEN
DBMS_OUTPUT.PUT_LINE ('Cannot remove dept ' ||
TO_CHAR(&p_deptno) || '. Employees exist. ');
END;
6、处理用户自定义的错误
这种错误一般是程序员根据具体的业务逻辑定义的应用类错误,需要先声明后使用: 定义和处理过程如下
DECLARE
e_invalid_department EXCEPTION;
BEGIN
UPDATE departments
SET department_name = &p_department_desc
WHERE department_id = &p_department_number;
IF SQL%NOTFOUND THEN
RAISE e_invalid_department;
END IF;
COMMIT;
EXCEPTION
WHEN e_invalid_department THEN
DBMS_OUTPUT.PUT_LINE('No such department id.');
END;
7、RAISE_APPLICATION_ERROR() 函数
对于用户自定义的业务错误,如果觉得先定义再使用很麻烦,那么 也可以简单的使用raise_application_error()
来简化处理。它可以无需预先定义错误,而在需要抛出错误的 地方直接使用此函数抛出例外,例外可以包含用户自定义的错误码和错误描述
BEGIN
...
DELETE FROM employees
WHERE manager_id = v_mgr;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20202,
'This is not a valid manager');
END IF;
...
...
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR (-20201,
'Manager is not a valid employee.');
END;
8、例外传递
当前块中不处理,传递到外层
DECLARE
. . .
e_no_rows exception;
e_integrity exception;
PRAGMA EXCEPTION_INIT (e_integrity, -2292);
BEGIN
FOR c_record IN emp_cursor LOOP
BEGIN
SELECT ...
UPDATE ...
IF SQL%NOTFOUND THEN
RAISE e_no_rows;
END IF;
END;
END LOOP;
EXCEPTION
WHEN e_integrity THEN ...
WHEN e_no_rows THEN ...
END;