PL/SQL处理例外

--一.例外简介
--1.例外分类:预定义例外,非预定义例外,自定义例外
--2.处理例外:例外传递-->捕捉例外

--二.处理预定义例外
--见ORALCE预定义异常列表

--三.处理非预定义例外
--非预定义例外用来处理与预定义例外无关的ORACLE错误,若未处理,ORALCE错误传递给调用环境
--DEMO
SQL> SET SERVEROUTPUT ON;
SQL> DECLARE
  2    --定义例外
  3    e_integrity EXCEPTION;
  4    --关联例外与ORACLE错误
  5    PRAGMA EXCEPTION_INIT(e_integrity,-2291);
  6  BEGIN
  7    UPDATE emp SET deptno=&dno WHERE empno=&eno;
  8  EXCEPTION
  9    --引用例外
 10    WHEN e_integrity THEN
 11      dbms_output.put_line('该部门不存在');
 12    END;
 13  /
输入 dno 的值:  11
输入 eno 的值:  7788
原值    7:   UPDATE emp SET deptno=&dno WHERE empno=&eno;
新值    7:   UPDATE emp SET deptno=11 WHERE empno=7788;
该部门不存在

PL/SQL 过程已成功完成。

--四.处理自定义例外
--自定义例外处理处理与ORACLE错误无关,由开发人员为特定情况所定义的例外
--DEMO
SQL> SET SERVEROUTPUT ON;
SQL> DECLARE
  2    --定义例外
  3    e_integrity EXCEPTION;
  4    --关联例外与ORACLE错误
  5    PRAGMA EXCEPTION_INIT(e_integrity,-2291);
  6
  7    --自定义例外
  8    e_no_employee EXCEPTION;
  9  BEGIN
 10    UPDATE emp SET deptno=&dno WHERE empno=&eno;
 11    IF SQL%NOTFOUND THEN
 12      RAISE e_no_employee;
 13    END IF;
 14  EXCEPTION
 15    --引用例外
 16    WHEN e_integrity THEN
 17      dbms_output.put_line('该部门不存在');
 18    WHEN e_no_employee THEN
 19      dbms_output.put_line('该雇员不存在');
 20    END;
 21  /
输入 dno 的值:  10
输入 eno 的值:  1111
原值   10:   UPDATE emp SET deptno=&dno WHERE empno=&eno;
新值   10:   UPDATE emp SET deptno=10 WHERE empno=1111;
该雇员不存在

PL/SQL 过程已成功完成。

--五.使用例外函数
--1.SQLCODE,SQLERRM
--SQLCODE用于返回ORACLE错误号
--SQLERRM用于返回该错误号所对应的错误消息
SQL> undef v_sal
SQL> DECLARE
  2    v_ename emp.ename%TYPE;
  3  BEGIN
  4    SELECT ename INTO v_ename FROM emp
  5      WHERE sal=&&v_sal;
  6    dbms_output.put_line('雇员名:'||v_ename);
  7  EXCEPTION
  8    WHEN NO_DATA_FOUND THEN
  9      dbms_output.put_line('不存在工资为:'||&v_sal||'的雇员');
 10    WHEN OTHERS THEN
 11      dbms_output.put_line('错误号:'||SQLCODE);
 12      dbms_output.put_line('错误信息:'||SQLERRM);
 13  END;
 14  /
输入 v_sal 的值:  9876
原值    5:     WHERE sal=&&v_sal;
新值    5:     WHERE sal=9876;
原值    9:     dbms_output.put_line('不存在工资为:'||&v_sal||'的雇员');
新值    9:     dbms_output.put_line('不存在工资为:'||9876||'的雇员');
不存在工资为:9876的雇员

PL/SQL 过程已成功完成。

--2.RAISE_APPLICATION_ERROR在PL/SQL应用程序中自定义错误消息
--该过程只能在数据库端的子程序中执行,而不能在匿名块或客户端的子程序中使用
--语法:raise_application_error(error_number,message[,{TRUE,FALSE}]);
--error_number:定义错误号,错误号必须是在-20000至-20999之间的负整数
--message:指定错误消息
--TRUE:该错误会与之前的错误一起放在堆栈中保存
--FALSE:默认值,替换先前的所有错误
--DEMO
SQL> CREATE or REPLACE PROCEDURE raise_comm
  2    (eno NUMBER,commission NUMBER)
  3  IS
  4    v_comm emp.comm%TYPE;
  5  BEGIN
  6    SELECT comm INTO v_comm FROM emp WHERE empno=eno;
  7    IF v_comm IS NULL THEN
  8      RAISE_APPLICATION_ERROR(-20001,'该雇员无补助');
  9    END IF;
 10  EXCEPTION
 11    WHEN NO_DATA_FOUND THEN
 12      dbms_output.put_line('该雇员不存在');
 13  END;
 14  /

过程已创建。

SQL> exec raise_comm(7788,100)
BEGIN raise_comm(7788,100); END;

*1 行出现错误:
ORA-20001: 该雇员无补助
ORA-06512: 在 "SCOTT.RAISE_COMM", line 8
ORA-06512: 在 line 1

--六.PL/SQL编译警告
--1.PL/SQL警告分类
--SEVERE:该种警告用于检查可能出现的不可预料结果或错误结果,例如参数的别名问题。
--PERFORMANCE:该类警告用于检查可能引起的性能问题,例如在执行INSERT操作时,为NUMBER列提供了VARCHAR2类型的数据。
--INFORMATION:该类警告用于检查子程序中的死代码。
--ALL:用于检查所有警告。

--2.控制PL/SQL警告信息
ALTER SYSTEM SET PLSQL_WARNINGS='ENABLE:ALL';
ALTER SESSION SET PLSQL_WARNINGS='ENABLE:PERFORMANCE';
ALTER PROCEDURE hello COMPILE PLSAL_WARNINGS='ENABLE:PERFORMANCE';
ALTER SESSION SET PLSQL_WARNINGS='DISABLE:ALL';
ALTER SESSION SET PLSQL_WARNINGS='ENABLE:SEVERE','DISABLE:PERFORMANCE','ERROR:06002';
CALL DBMS_WARNINGS.SET_WARNING_SETTING_STRING('ENABLE:ALL','SESSION');

--3.使用PL/SQL编译警告
--3.1检测死代码
SQL> CREATE OR REPLACE PROCEDURE dead_code AS
  2    x NUMBER:=10;
  3  BEGIN
  4    IF x=10 THEN
  5      x:=20;
  6    ELSE
  7      x:=100;
  8    END IF;
  9  END dead_code;
 10  /

过程已创建。

SQL> ALTER SESSION SET PLSQL_WARNINGS='ENABLE:INFORMATIONAL';

会话已更改。

SQL> ALTER PROCEDURE dead_code COMPILE;

SP2-0805: 过程已变更, 但带有编译警告

SQL> show errors;
PROCEDURE DEAD_CODE 出现错误:

LINE/COL ERROR
-------- -----------------------------------------------------------------
4/7      PLW-06002: 无法执行的代码
7/5      PLW-06002: 无法执行的代码

--3.2检测引起性能问题的代码
SQL> show errors;
PROCEDURE DEAD_CODE 出现错误:

LINE/COL ERROR
-------- -----------------------------------------------------------------
4/7      PLW-06002: 无法执行的代码
7/5      PLW-06002: 无法执行的代码
SQL> ed a

SQL> CREATE OR REPLACE PROCEDURE update_sal
  2    (name VARCHAR2,salary VARCHAR2)
  3  IS
  4  BEGIN
  5    UPDATE emp SET sal=salary WHERE ename=name;
  6  END;
  7  /

过程已创建。

SQL> ALTER SESSION SET PLSQL_WARNINGS='ENABLE:PERFORMANCE';

会话已更改。

SQL> ALTER PROCEDURE update_sal COMPILE;

SP2-0805: 过程已变更, 但带有编译警告

SQL> show errors;
PROCEDURE UPDATE_SAL 出现错误:

LINE/COL ERROR
-------- -----------------------------------------------------------------
5/22     PLW-07202: 绑定类型可能会导致从列类型转换为其它类型

 ORALCE预定义EXCEPTION列表

常见预定义例外 ORACLE服务错误号 错误描述
ACCESS_INTO_NULL ORA-06530 引用对象属性前,必须先初始化对象
CASE_NOT_FOUND ORA-06592 CASE语句中没有包含必须的条件分支且未包含ELSE子句
COLLECTION_IS_NULL ORA-06531 在给集合元素赋值前,必须首先初始化集合元素
CURSOR_ALREADY_OPEN ORA-06511 重新打开已经打开的游标
DUP_VAL_ON_INDEX ORA-00001 在唯一索引所对应的列上键入重复值时
INVALID_VURSOR ORA-01001 视图在不合法的游标上执行操作时(关闭未打开的游标,从未打开的游标上提取数据)
INVALID_NUMBER ORA-01722 内嵌SQL不能有效地将字符转换成数字时
NO_DATA_FOUND ORA-01403 当执行SELECT   INTO未返回行或引用了索引表未初始化的元素时
TOO_MANY_ROWS ORA-01422 当执行SELECT   INTO返回值超过一行时
ZERO_DIVIDE ORA-01476 除0
SUBSCRIPT_BEYOND_COUNT ORA-06533 使用嵌套表或VARRAY,元素下标超出元素的范围时
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 使用嵌套表或VARRAY,元素下标为负数时
VALUE_ERROR ORA-06502 所赋的值比变量长度要大时
其他预定义例外 ORACLE服务错误号 错误描述
LOGIN_DENIED ORA-01017 PL/SQL应用程序需要连接到ORALCE数据库,提供了不正确的用户名或口令时
NOT_LOGGEN_ON ORA-01012 PL/SQL应用程序未连接到ORALCE数据库,执行了PL/SQL块中访问数据库时
PROGRAM_ERROR ORA-06501 存在PL/SQL内部错误(用户可能需要重新安装数据字典和PL/SQL系统包)
ROWTYPE_MISMATH ORA-06504 当赋值时,宿主游标变量与PL/SQL游标返回的类型不兼容
SELF_IS_NULL ORA-30625 当使用对象类型时,如果在NULL实例上调用成员的方法
STORAGE_ERROR ORA-06500 PL/SQL运行时,超出内存空间或内存被损坏
SYS_INVALID_ROWID ORA-01410 字符串转变成ROWID时,必须使用有效的字符串,如无效时
TIMOUT_ON_RESOURCE ORA-00051 ORACLE在等待池里出现超时

posted on 2012-08-31 17:51  wean  阅读(1449)  评论(0编辑  收藏  举报

导航