PL/SQL_处理例外1(预定义例外)

当开发PL/SQL应用程序时,为了提高应用程序的健壮性,开发人员必须考虑PL/SQL程序可能出现的各种错误,并进行相应的错误处理。如果不进行错误处理,在出现运行错误时,会终止PL/SQL程序的运行,并显示错误信息。在编写PL/SQL程序时,通过使用例外(Exception)可以处理运行错误。
例外分类
为了处理PL/SQL应用程序的各种错误,开发人员可以使用各种类型的例外。Oracle提供了预定义例外、非预定义例外和自定义例外等三种例外类型。
在PL/SQL块中捕捉并处理例外需要使用额外的处理部分来完成,例外处理部分是 关键字EXCEPTION开始的,语法如下所示:
EXCEPTION
WHEN exception1 [OR exception2...] THEN
statement1;
statement2;
...
[WHEN exception3 [OR exception4...] THEN
statement1;
statement2;
...
[when OTHERS THEN
statement1;
statement2;
...
示例:
DECLARE
  v_ename emp.ename%TYPE;
BEGIN
  SELECT ename INTO  v_ename FROM emp WHERE empno = &NO;
  dbms_output.put_line(‘雇员名:‘ || v_ename);
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      dbms_output.put_line(‘雇员号不存在,请核实雇员名‘);
END;

处理预定义例外

预定义例外是指由PL/SQL所提供的系统例外。当PL/SQL应用程序违反了Oracle规则或系统限制时,则会隐含地触发一个内部例外。
1、常用预定义例外
(1)ACCESS_INTO_NULL
该例外对应于ORA-06530错误。当开发对象类型应用时,在引用对象属性之前,必须首先初始化对象。
建立对象类型:
CREATE TYPE emp_type AS object(
  NAME VARCHAR2(10),
  sal NUMBER(6,2)
);
捕捉并处理该例外的示例如下:
DECLARE
  v_emp emp_type;
  --v_emp emp_type := emp_type(‘‘,0);
BEGIN
  v_emp.name := ‘张三‘;
  v_emp.sal := 1000;
  EXCEPTION
    WHEN ACCESS_INTO_NULL THEN
      dbms_output.put_line(‘首先初始化emp‘);
END;
(2)CASE_NOT_FOUND
该例外对应于ORA-06592错误。当在PL/SQL块中编写CASE语句时,如果在WHEN子句中没有包含必须的条件分支,并且没有包含ELSE子句,就会隐含地触发CASE_NOT_FOUND例外。
DECLARE
  v_sal emp.sal%TYPE;
BEGIN
  SELECT sal INTO v_sal FROM emp WHERE empno = &NO;
  CASE
    WHEN v_sal < 1000 THEN
      UPDATE emp SET sal = sal + 100 WHERE empno = &NO;
    WHEN v_sal < 2000 THEN
      UPDATE emp SET sal = sal + 150 WHERE empno = &NO;
    WHEN v_sal < 3000 THEN
      UPDATE emp SET sal = sal + 200 WHERE empno = &NO;
  END CASE;
  EXCEPTION
    WHEN CASE_NOT_FOUND THEN
      dbms_output.put_line(‘在CASE语句中缺少与‘ || v_sal || ‘相关的条件‘);
END;
(3)COLLECTION_IS_NULL
该例外对应于ORA-06531错误。在给集合元素(嵌套表或VARRAY类型)赋值前,必须首先初始化集合元素。如果没有初始化集合元素,则会隐含地触发COLLECTION_IS_NULL例外。
DECLARE
  TYPE ename_table_type IS TABLE OF emp.ename%TYPE;
  ename_table ename_table_type;
BEGIN
  SELECT ename INTO ename_table(1) FROM emp WHERE empno = &NO;
  dbms_output.put_line(‘雇员名:‘ || ename_table(1));
  EXCEPTION
    WHEN COLLECTION_IS_NULL THEN
      dbms_output.put_line(‘必须使用构造方法初始化集合元素‘);
END;
(4)CURSOR_ALREADY_OPEN
该例外对应于ORA-06511错误。当重新打开已经打开的游标时,会隐含地触发例外CURSOR_ALREADY_OPEN。
DECLARE
  CURSOR cur_emp IS
  SELECT ename,sal FROM emp;
BEGIN
  --打开游标
  OPEN cur_emp;
  FOR emp_record IN cur_emp LOOP
    dbms_output.put_line(emp_record.ename);
  END LOOP;
  EXCEPTION
    WHEN CURSOR_ALREADY_OPEN THEN
      dbms_output.put_line(‘游标已经打开‘);
END;
(5)DUP_VAL_ON_INDEX
该例外对应于ORA-00001错误。当在惟一索引所对应的列上键入重复值时,会隐含地触发例外DUP_VAL_ON_INDEX。
BEGIN
  UPDATE dept SET deptno = 40 WHERE deptno = &NO;
  EXCEPTION
    WHEN DUP_VAL_ON_INDEX THEN
      dbms_output.put_line(‘在deptno列上不允许重复值‘);
END;
(6)INVALID_CURSOR
该例外对应于ORA-01001错误。当试图在不合法的游标上执行操作时,会隐含地触发例外INVALID_CURSOR。例如,如果要从未打开的游标提取数据,或者关闭未打开的游标,则会触发该例外。
DECLARE
  CURSOR cur_emp IS
  SELECT ename,sal FROM emp;
  TYPE emp_record_type IS RECORD(
    ename emp.ename%TYPE,
    sal emp.sal%TYPE
  );
  emp_record emp_record_type;
BEGIN
  --未打开游标
  FETCH cur_emp INTO emp_record;
  --关闭游标
  CLOSE cur_emp;
  EXCEPTION
    WHEN INVALID_CURSOR THEN
      dbms_output.put_line(‘请检查游标是否已经打开‘);
END;
(7)INVALID_NUMBER
该例外对应于ORA-01722错误。当内嵌SQL语句不能有效地将字符转变成数字时,会隐含地触发例外INVALID_NUMBER,例如数字值"100“被写成"1OO"。
BEGIN
  UPDATE emp SET sal = sal + ‘1OO‘;
  EXCEPTION
    WHEN INVALID_NUMBER THEN
      dbms_output.put_line(‘输入的数字值不正确‘);
END;
(8)NO_DATA_FOUND
该例外对应于ORA-01403错误。当执行SELECT INTO未返回行,或者引用了索引表未初始化的元素时,会隐含地触发例外NO_DATA_FOUND。
DECLARE
  v_sal emp.sal%TYPE;
BEGIN
  SELECT sal INTO v_sal FROM emp
  WHERE LOWER(ename) = LOWER(‘&ename‘);
  dbms_output.put_line(‘工资:‘ || v_sal);
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      dbms_output.put_line(‘不存在该雇员‘);
END;
(9)TOO_MANY_ROWS
该例外对应于ORA-01422错误。当执行SELECT INTO语句时,如果返回超过一行,则会触发该例外。
DECLARE
  v_ename emp.ename%TYPE;
BEGIN
  SELECT ename INTO v_ename FROM emp
  WHERE sal = 3600;
  EXCEPTION
    WHEN TOO_MANY_ROWS THEN
      dbms_output.put_line(‘返回多行‘);
END;
(10)ZERO_DIVIDE
该例外对应于ORA-01476错误。当运行PL/SQL块时,如果使用数字值除0,则会隐含地触发该例外。
DECLARE
  num1 INT := 100;
  num2 INT := 0;
  num3 NUMBER(6,2);
BEGIN
  num3 := num1/num2;
  EXCEPTION
    WHEN ZERO_DIVIDE THEN
      dbms_output.put_line(‘除数不能为0‘);
END;
(11)SUBSCRIPT_BEYOND_COUNT
该例外对应于ORA-06533错误。当使用嵌套表或VARRAY元素时,如果元素下标超出了嵌套表或VARRAY元素的范围,则会隐含地触发SUBSCRIPT_BEYOND_COUNT例外。
DECLARE
  TYPE emp_array_type IS VARRAY(20) OF VARCHAR2(20);
  emp_array emp_array_type := emp_array_type(‘‘,‘‘);
BEGIN
  dbms_output.put_line(emp_array(3));
  EXCEPTION
    WHEN SUBSCRIPT_BEYOND_COUNT THEN
      dbms_output.put_line(‘超出下标范围‘);
END;
(12)SUBSCRIPT_OUTSIDE_LIMIT
该例外对应于ORA-06532错误。当使用嵌套表或VARRAY元素时,如果元素下标为负值,则会隐含地触发SUBSCRIPT_BEYOND_COUNT例外。
DECLARE
  TYPE emp_array_type IS VARRAY(20) OF VARCHAR2(20);
  emp_array emp_array_type := emp_array_type(‘‘,‘‘);
BEGIN
  dbms_output.put_line(emp_array(-1));
  EXCEPTION
    WHEN SUBSCRIPT_OUTSIDE_LIMIT THEN
      dbms_output.put_line(‘嵌套表或VARRAY下标不能为负‘);
END;
(13)VALUE_ERROR
该例外对应于ORA-06502错误。当在PL/SQL块中执行赋值操作时,如果变量长度不足以容纳实际数据,则会隐含地触发例外VALUE_ERROR。
DECLARE
  v_ename VARCHAR2(2);
BEGIN
  SELECT ename INTO v_ename FROM emp WHERE empno = &NO;
  dbms_output.put_line(v_ename);
  EXCEPTION
    WHEN VALUE_ERROR THEN
      dbms_output.put_line(‘变量尺寸不足‘);
END;

2、其他预定义例外

除了在PL/SQL块中经常需要处理常见的预定义例外之外,某些情况下你可能还需要使用其他预定义例外。下面简单介绍这些例外的作用。
(1)LOGIN_DENIED
该例外对应于ORA-01017错误。当PL/SQL应用程序需要连接到Oracle数据库时,如果提供了不正确的用户名或口令,则会隐含地触发例外LOGIN_DENIED。
(2)NOT_LOGGED_ON
该例外对应于ORA-01012错误。如果应用程序没有连接到Oracle数据库,那么在执行PL/SQL块中访问数据库时会隐含地触发例外NOT_LOGGED_ON。
(3)PROGRAM_ERROR
该例外对应于ORA-06501错误。如果出现该错误,则表示存在PL/SQL内部问题,用户此时可能需要重新安装数据字典和PL/SQL系统包。
(4)ROWTYPE MISMATCH
该例外对应于ORA-06504错误。当执行赋值操作时,如果宿主游标变量和PL/SQL游标变量的返回类型不兼容,那么会隐含地触发例外ROWTYPE_MISMATCH。
(5)SELF_IS_NULL
该例外对应于ORA-30625错误。当使用对象类型时,如果在null实例上调用成员方法,则会隐含地触发例外SELF_IS_NULL。
(6)STORAGE_ERROR
该例外对应于ORA-06500错误。PL/SQL块运行时,如果超出内存空间或者内存被损坏,则会隐含地触发例外STORAGE_ERROR。
(7)SYS_INVALID_ROWID
该例外对应于ORA-01410错误。当将字符串转变为ROWID时,必须使用有效的字符串。如果使用了无效的字符串,会隐含地触发例外SYS_INVALID_ROWID。
(8)TIMEOUT_ON_RESOURCE
该例外对应于ORA-00051错误。当如果Oracle在等待资源时出现超时错误,则会隐含地触发例外TIMEOUT_ON_RESOURCE。

PL/SQL_处理例外1(预定义例外),古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。