Oracle PLSQL

PLSQL中的例外处理

PLSQL中的例外一般有两种:
1、Oracle 内部错误抛出的例外:这又分为预定义例外(有错误号+常量定义)和 非预定义例外 (仅有错误号,无常量定义)
2、程序员显式的抛出的例外

1、内部错误抛出的例外

A.预定义例外(有错误号+常量定义)

B.非预定义例外(仅有错误号,无常量定义)

2、显式的抛出的例外

3、PLSQL中的例外处理的一般语法

  1. EXCEPTION
  2. WHEN exception1 [OR exception2 . . .] THEN
  3. statement1;
  4. statement2;
  5. . . .
  6. [WHEN exception3 [OR exception4 . . .] THEN
  7. statement1;
  8. statement2;
  9. . . .]
  10. [WHEN OTHERS THEN
  11. statement1;
  12. statement2;
  13. . . .]

A.PLSQL定义的常见例外

Oracle 预定义好的常见例外:
–NO_DATA_FOUND
–TOO_MANY_ROWS
–INVALID_CURSOR
–ZERO_DIVIDE
–DUP_VAL_ON_INDEX
处理预定义的例外:有些常见例外,Oracle 都已经预定义好了,使用时无需预先声明,比如: NO_DATA_FOUND 和 TOO_MANY_ROWS 是最常见的例外

  1. BEGIN
  2. . . .
  3. EXCEPTION
  4. WHEN NO_DATA_FOUND THEN
  5. statement1;
  6. WHEN TOO_MANY_ROWS THEN
  7. statement1;
  8. WHEN OTHERS THEN
  9. statement1;
  10. statement2;
  11. END;

B.OTHERS的处理

Others表明程序员未能预计到这种错误,所以全部归入到others 里面去了

4、Oracle 错误号和错误描述

Oracle 提供了两个内置函数 SQLCODE 和 SQLERRM 分别用来返回Oracle 错误号和错误描述

  1. DECLARE
  2. v_error_code NUMBER;
  3. v_error_message VARCHAR2(255);
  4. BEGIN
  5. ...
  6. EXCEPTION
  7. ...
  8. WHEN OTHERS THEN
  9. ROLLBACK;
  10. v_error_code := SQLCODE ;
  11. v_error_message := SQLERRM ;
  12. INSERT INTO errors
  13. VALUES(v_error_code, v_error_message);
  14. END;

5、处理非预定义的Oracle错误

此类错误属于Oracle错误,有编号,但无错误名称定义,使用时需要先声明,并 进行错误初始化
image.png

  1. DEFINE p_deptno = 10
  2. DECLARE
  3. e_emps_remaining EXCEPTION;
  4. PRAGMA EXCEPTION_INIT
  5. (e_emps_remaining, -2292);
  6. BEGIN
  7. DELETE FROM departments
  8. WHERE department_id = &p_deptno;
  9. COMMIT;
  10. EXCEPTION
  11. WHEN e_emps_remaining THEN
  12. DBMS_OUTPUT.PUT_LINE ('Cannot remove dept ' ||
  13. TO_CHAR(&p_deptno) || '. Employees exist. ');
  14. END;

6、处理用户自定义的错误

这种错误一般是程序员根据具体的业务逻辑定义的应用类错误,需要先声明后使用: 定义和处理过程如下
image.png

  1. DECLARE
  2. e_invalid_department EXCEPTION;
  3. BEGIN
  4. UPDATE departments
  5. SET department_name = &p_department_desc
  6. WHERE department_id = &p_department_number;
  7. IF SQL%NOTFOUND THEN
  8. RAISE e_invalid_department;
  9. END IF;
  10. COMMIT;
  11. EXCEPTION
  12. WHEN e_invalid_department THEN
  13. DBMS_OUTPUT.PUT_LINE('No such department id.');
  14. END;

7、RAISE_APPLICATION_ERROR() 函数

对于用户自定义的业务错误,如果觉得先定义再使用很麻烦,那么 也可以简单的使用raise_application_error() 来简化处理。它可以无需预先定义错误,而在需要抛出错误的 地方直接使用此函数抛出例外,例外可以包含用户自定义的错误码和错误描述

  1. BEGIN
  2. ...
  3. DELETE FROM employees
  4. WHERE manager_id = v_mgr;
  5. IF SQL%NOTFOUND THEN
  6. RAISE_APPLICATION_ERROR(-20202,
  7. 'This is not a valid manager');
  8. END IF;
  9. ...
  10. ...
  11. EXCEPTION
  12. WHEN NO_DATA_FOUND THEN
  13. RAISE_APPLICATION_ERROR (-20201,
  14. 'Manager is not a valid employee.');
  15. END;

8、例外传递

当前块中不处理,传递到外层

  1. DECLARE
  2. . . .
  3. e_no_rows exception;
  4. e_integrity exception;
  5. PRAGMA EXCEPTION_INIT (e_integrity, -2292);
  6. BEGIN
  7. FOR c_record IN emp_cursor LOOP
  8. BEGIN
  9. SELECT ...
  10. UPDATE ...
  11. IF SQL%NOTFOUND THEN
  12. RAISE e_no_rows;
  13. END IF;
  14. END;
  15. END LOOP;
  16. EXCEPTION
  17. WHEN e_integrity THEN ...
  18. WHEN e_no_rows THEN ...
  19. END;