数据程序设计4 Oracle异常处理

目录

PL/SQL异常

异常类型

预定义异常

非预定义异常

捕获异常的函数

用户定义的异常

异常传递

Raise_Application_Error过程


PL/SQL异常

即运行时发生的错误。

异常的触发:

  • 发生一个oracle错误时
  • 使用RAISE子句显式触发

处理异常:

  • 处理机截获
  • 在调用环境中异常传播

例子:

DECLARE
    v_ename    emp.ename%TYPE;
    v_empno    NUMBER(4) := 7369;
BEGIN
    select ename
    into v_ename
    from emp
    where empno=v_empno;
    dbms_output.put_line(v_ename);
EXCEPTION
    WHEN OTHERS THEN
    dbms_output.put_line('others');
END;

正常运行,输出SMITH

当修改为不存在的员工号时

DECLARE
    v_ename    emp.ename%TYPE;
    v_empno    NUMBER(4) := 736;
BEGIN
    select ename
    into v_ename
    from emp
    where empno=v_empno;
    dbms_output.put_line(v_ename);
EXCEPTION
    WHEN OTHERS THEN
    dbms_output.put_line('others');
END;

没有这个数据,输出others;如果没有异常处理的话,程序则会终止掉。

异常类型

                       异常                         描述                                  处理
Oracle服务器预定义异常 Oracle中有名字的错误 不需声明,可以由Oracle服务器隐式地触发
Oracle 服务器非预定义的异常 其它所有非标准的Oracle服务器错误 在声明部分声明,可以由Oracle服务器隐式地触发
用户定义异常 由开发者决定的异常情形 在声明部分声明,由程序显式地触发

语法:

EXCEPTION
    WHEN exception1 [or exception2...] THEN
        statement;statement;...
    WHEN exception3 [or exception4...]THEN
        statement;statement;...
    [WHEN OTHERS THEN
        statement;statement;...]

注意:

  • 在异常部分WHEN子句没有数量限制
  • WHEN OTHERS 是最后一 个子句
  • 异常处理部分从关键字EXCEPTION开始
  • 当异常抛出后,控制无条件转到异常处理部分
  • 在离开块之前只能执行一种异常处理

当程序出了异常的时候,程序正常的流程就不再走了。

预定义异常

异常情况名 错误代码 描述
DUP_VAL_ON_INDEX 0RA-00001 试图更新或插入重复记录
INVALID_CURSOR 0RA-01001 非法游标操作
INVALID_NUMBER 0RA-01722 字符串向数字转换失败
NO_DATA_FOUND ORA-01403 执行的SELECT没有查到数据
TOO_MANY_ROWS ORA-01427 未使用游标,SELECT语句返回了多行数据
VALUE_ERROR 0RA-06502 出现数字、数据转换、字符串或限制型错误
ZERO_DIVIDE ORA-01476 被零除

非预定义异常

Oracle错误但是只有代码没有名字。

DECLARE
    e_emp_cons    EXCPTION;    
    PRAGMA EXCEPTION_ INIT(e_emp_cons,-00001);

捕获异常的函数

  • SQLCODE:返回错误代码
  • SQLERRM:返回错误值相关联的信息

例子

DECLARE
    v_ename    emp.ename%TYPE;
    v_empno    NUMBER(4) := 736;
BEGIN
    select ename
    into v_ename
    from emp
    where empno=v_empno;
    dbms_output.put_line(v_ename);
EXCEPTION
    WHEN OTHERS THEN
    dbms_output.put_line(SQLCODE);
    dbms_output.put_line(SQLERRM);
END;

但是在实际中,不会这样输出错误,而是会使用一个异常表来记录

CREAT TABLE ERRORS(
objname VARCAHR2(100),
eDATE DATE,
SQLCODE NUMBER(6),
SQLERRM VARCHAR2(200)
)

那么代码可以改成

DECLARE
    v_ename    emp.ename%TYPE;
    v_empno    NUMBER(4) := 736;
    verrcode    NUMBER(6);
    v_errmsg    VARCHAR2(200);
BEGIN
    select ename
    into v_ename
    from emp
    where empno=v_empno;
    dbms_output.put_line(v_ename);
EXCEPTION
    WHEN OTHERS THEN
    verrcode := SQLCODE;
    v_errmsg := SQLERRM
    dbms_output.put_line(SQLCODE);
    dbms_output.put_line(SQLERRM);
    VALUES('',sysdate,verrcode,v_errmsg)
END;

这样就可以把初始值放在一个表中。

用户定义的异常

在oracle中不算错误但是我们觉得是错误。需要手动用RAISE子句触发。

例子

DECLARE
    e_ too_ many    EXCEPTION;
BEGIN
    update emp
    set sal= 5000
    where deptno=&xp_ deptno;
    if SOL %ROWCOUNT >2 then
        RAISE e_ too_ many;
    end if;
EXCEPTION
    when e_ too_ many then
        dbms_ output.put_ line('涨工资人数'|| SQL%ROWCOUNT||'人,太多了);
        rollback;
End;

异常传递

异常如果没有做处理,会向上一次传。

Raise_Application_Error过程

模拟出现一个错误,产生一个类似于异常的对话框并终止程序,错误编号在-20000~-20999之间,错误消息长度最大为2048字节

DECLARE
    e_ name    exception;
    pragma exception_ init(e_ name, 20202);
BEGIN
    delete from emp where deptno=90;
    if SQL%NOTFOUND then
        Raise_ Application_ Error(- 20202,’部门不存在);
    end if;
EXCEPTION
    when e_ name then
        dbms_ output. put line(sqlcode); 
        dbms_ output.put line(sqlerrm);
END;

这个代码的作用是删除人员时发现没有这个部门,会弹出一个对话框并终止程序,提示部门不存在。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章