Oracle 学习笔记12 —— 异常处理


   Oracle使用异常来处理,PL/SQL执行时发生的错误,这些异常都可以包括在PL/SQL程序的exception块中。Oracle提供了许多的内置的异常,用户也可以根据自己的需要定义异常。Oracle的异常可以分为3类:

  1> 预定义异常 Oracle中内置了大量异常。在PL/SQL中使用预定义的异常,以便检查用户代码的执行失败的原因。这些异常定义在Oracle的核心PL/SQL库中,用户可以在自己的PL/SQL异常处理部分使用名称对其进行标识。对这种异常情况的处理,用户无需在程序中定义,Oracle自己引发。

  2> 非预定义异常 非预定义异常数据库本身不知道,不能控制的错误。例如,操作类型崩溃;Oracle服务器错误;网络或者机器I/O错误等。对这种异常情况的处理,需要用户在程序中定义,然后由Oracle自动引发。

  3> 用户定义异常 违反业务逻辑时,开发人员明确定义并引发的异常。

1、预定义异常

当PL/SQL程序违反了Oracle的规定或超出了系统规定的限制时,就会隐式地引发一个预定义异常错误。下面是常见的预定义异常。

系统预定义异常
系统定义异常说明
ACCESS_INFO_NULL试图为某个未初始化对象的属性赋值。
CASE_NOT_FOUND在case语句中未包含相应相应的when字句,并且没有设置else语句。
COLLECTION_IS_NULL集合元素未初始化
CURSOR_ALREADY_OPEN试图打开一个已经打开的游标。游标在重新打开之前,必须关闭。
DUP_VAL_ON_INDEX试图在一个唯一性索引的列中存储冗余值
INVALID_CURSOR执行一个非法的游标操作,例如关闭一个未打开的游标。
INVALID_NUMBER试图将一个字符串转换为一个无效的数字。
LOGIN_DENIED试图使用无效的用户名和密码连接数据库
NO_DATA_FOUNDselect into语句没有返回数据,或者试图访问嵌套表中语句被删除的元素或未初始化的元素。
NOT_LOGINED_ERROR试图在没有连接数据的情况下访问数据的内容。
PROGRAM_ERRORpl/sql内部问题,可能需要重装数据字典和pl/sql系统包。
ROW_TYPE_MISMATCH主游标变量与PL/SQL变量的返回类型不同。
SELF_IS_NULL使用对象类型时,在NULL对象上调用对象方法。
STORAGE_ERRORPL/SQL程序使用完了内存或内存遭到破坏。
SUBSCRIPT_BEYOND_COUNT元素下标超过嵌套表或VARRAY的最大值。
SUBSCRIPT_OUTSIDE_LIMIT试图使用非法索引号引用嵌套表或VARRAY中的元素。
SYS_INVALID_ROWID字符串向ROWID转换时的错误。
TIMEOUT_ON_RESOURCEOracle在等待资源是超时。
TOO_MANY_ROWS执行SELECT INTO语句时,结果集大于一行。
VALUE_ERROR赋值时,变量长度不足以容纳实际数据。
ZERO_DIVIDE除数为0.

SQL> set serveroutput on
SQL> begin
  2    insert into emp(empno, ename,job,sal,deptno)
  3    values(7369, 'ATG', 'Tim', 1500, 20);
  4  exception
  5    when DUP_VAL_ON_INDEX then
  6       dbms_output.put_line('捕获DUP_VAL_ON_INDEX 异常');
  7       dbms_output.put_line('该主键值已经存在');
  8  end;
  9  /
捕获DUP_VAL_ON_INDEX 异常
该主键值已经存在

PL/SQL 过程已成功完成。

上边的例子试图使用已经存在的主键值向emp表添加新记录,这会因为违法主键约束而发生错误。

SQL> set serveroutput on
SQL> declare
  2    emp_row emp%rowtype;
  3  begin
  4    select *
  5    into emp_row
  6    from emp
  7    where deptno = 10;
  8  exception
  9    when others then
 10    dbms_output.put_line('异常错误(' || SQLCODE || ')');
 11    dbms_output.put_line(SQLERRM);
 12  end;
 13  /
异常错误(-1422)
ORA-01422: 实际返回的行数超出请求的行数

PL/SQL 过程已成功完成。

2、非预定义异常

在一个异常产生、被捕获并处理之前,它必须被定义。Oracle定义了几千个异常,绝大多数只有错误编号和相关描述,仅仅命名少量最常用的异常,即系统定义异常。


除此之外的绝大多数异常都未命名,这些异常就是非预定义异常,它们需要程序员对其命名。当然,只使用错误码也可以完成异常的处理,但是这种异常处理会使代码可读性非常差。为非预定义异常命名时,需要使用 pragma exception_init 语句为错误号关联一个名称,随后就可以向系统预定义异常一样进行处理。exception_init是编译时运行的一个函数,它只能出现在代码的声明部分,而异常名必须在此之前被定义。下边为-2292 关联了一个名称:

SQL> set serveroutput on
SQL> declare
  2    invalid_company_id exception;
  3    fk_delete_exception exception;
  4    pragma exception_init(fk_delete_exception, -2292);
  5  begin
  6    delete from dept
  7    where dname='SALES';
  8  exception
  9    when fk_delete_exception then
 10    dbms_output.put_line('该项目存在于另一个列表中。');
 11  end;
 12  /
该项目存在于另一个列表中。

PL/SQL 过程已成功完成。

在上面的例子中,由于要删除的部门仍在在emp表中引用,所以提示外键引用。

3、用户定义异常
系统预定义和非预定义异常都是有oracle判断的错误,在实际的应用中,开发人员可以根据具体的业务规则自定义异常。

SQL> set serveroutput on
SQL> declare
  2    salary_error exception; -- 定义薪金异常
  3    var_sal emp.sal%type;
  4  begin
  5
  6    select sal into var_sal from emp
  7    where empno = 7369;
  8
  9    if var_sal <= 800 then
 10      raise salary_error;  -- 抛出异常
 11    end if;
 12  exception
 13    when salary_error then
 14      dbms_output.put_line('穷人');
 15  end;
 16  /
穷人

PL/SQL 过程已成功完成。

SQL> set serveroutput on
SQL> declare
  2    var_comm number;
  3  begin
  4    select comm
  5    into var_comm
  6    from emp
  7    where ename='TURNER';
  8
  9    if var_comm = 0 then
 10      raise zero_divide; -- 抛出系统异常
 11    end if;
 12  exception
 13
 14    when zero_divide then
 15      dbms_output.put_line('补贴为0!');
 16  end;
 17  /
补贴为0!

PL/SQL 过程已成功完成。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值