本文共 3331 字,大约阅读时间需要 11 分钟。
如果PL/SQL 发生了一个错误,无论是系统错误还是应用的错误,都会抛出一个异常。当前PL/SQL块中执行单元就会暂定处理,如果当前块有一个异常处理单元的话,控制会转移到当前块的异常处理单元来处理异常。完成了异常处理后就不能再返回到当前块,相反,控制会转移到外层包围块,如果有的话。
异常分类:
语法如下:
exception_name EXCEPTION;
有两种引用方式:
RAISE exception_name;
WHEN exception_name THEN
Oracle只给一小部分异常定义了名字;数据库里还有其他的错误只定义了一个错误数字和消息;
可以使用EXCEPTION_INIT编译命令,把异常名称和内部错误代码关联在一起:
例如:
PROCEDURE my_procedureIS invalid_month EXCEPTION; PRAGMA EXCEPTION_INIT(invalid_month, -1843);BEGIN ...EXCEPTION WHEN invalid_month THEN
错误数字可以使用符合下列约束的任意整数:
最重要的也是最常用的命名异常可以在PL/SQL的 STANDARD 包中找到。
例如,代码中处理 NO_DATA_FOUND 异常:
WHEN NO_DATA_FOUND THEN或者WHEN STANDARD.NO_DATA_FOUND THEN
有三种方法抛出异常:
语法如下:
RAISE exception_name;RAISE package_name.exception_name;RAISE;
第3种形式只可以用在异常处理单元的WHEN语句中,用于在异常处理单元中再次抛出同一个异常:
例如:
EXCEPTION WHEN NO DATA fOUND THEN ... -- 现在再把未处理的NO_DATA_fOUND 传播到外层包围块中 RAISE;
使用这个过程的好处在于,可以给异常加上一段错误消息。
一旦这个过程运行,当前PL/SQL块的执行就立即终止,对OUT和IN OUT参数所做的修改会被撤销,对于全局数据结构做的修改,如包变量,数据库对象不会回滚。用户必须明确调用 ROLLBACK 来撤销DML操作引起的修改。
语法如下:
PROCEDURE RAISE_APPLICATION_ERROR(num binary_integer,msg varchar2,keeperorstack boolean default FALSE);
一旦有异常抛出,当前PL/SQL块就会终止正常执行,把控制传递给异常处理单元。这个异常或者被当前PL/SQL块中的处理句柄处理,或者抛给外层块。
要捕获或者处理某个异常,必须专门为这个异常写一个异常句柄。异常处理代码在程序中的位置是在所有可执行语句之后,在块的END语句之前。
EXCEPTION关键字指示了异常处理单元的开始以及每个独立的异常句柄:
DECLARE ...declarations...BEGIN ...executable statements...[ EXCEPTION ...exception handles... ]END;
异常句柄(exception handles)的语法:
WHEN exception_name [ OR exception_name ... ]THEN executable statements或者WHEN OTHERSTHEN executable statements
一旦PL/SQL块中抛出了异常,正常执行单元被终止然后控制传递到异常处理单元。一旦块中有异常抛出就再也不能回到该块的执行单元了。
然而,在某些时候,我们想要异常过后还能继续执行的能力。
采用如下方法,可以保证未抛出异常的语句都有机会得到执行:
例如:
PROCEDURE change_date ISBEGIN BEGIN DELETE FROM employees WHERE...; EXCEPTION WHEN OTHERS THEN log_error; END; BEGIN UPDATE company SET...; EXCEPTION WHEN OTHERS THEN log_error; END; BEGIN INSERT INTO company_history SELECT • FROM company WHERE...; EXCEPTION WHEN OTHERS THEN log_error; END;END;
在执行单元抛出的异常总是在当前块中被处理 —— 如果匹配的句柄存在。通过给任何语句加上一个BEGIN,之后加上一个EXCEPTION单元和END语句构建一个“虚拟块”出来,可以在代码中控制异常的失败范围。
WHEN OTHERS语句可以捕获所有其他的未处理异常。
可以利用内置异常函数比如SQLCODE 和 DBMS_UTILITY.FORMAT_ERROR_STACK获得发生的错误的信息。
转载地址:http://mxwfi.baihongyu.com/