缺省情况下,在 PL/SQL 程序中遇到的任何错误都将停止执行程序。您可以使用 EXCEPTION 节来捕获错误以及从出错状态恢复。
异常处理程序的语法是 BEGIN 块的语法扩展。
.---------------. V | >>-+--------------------------+--BEGIN----+-----------+-+-------> | .-------------. | '-statement-' | V | | '-DECLARE----declaration-+-' >--+------------------------------------------------------------------------------------------+--> | .-------------------. .-------------------. | | V | V | | '-EXCEPTION--WHEN--exception-condition----+---------------+-+--THEN----handler-statement-+-' '-OR--condition-' >--END---------------------------------------------------------><
如果未发生错误,那么此块仅仅执行 statement 并将控制权传递到 END 之后的语句。但是,如果在执行 statement 时发生错误,那么会放弃对 statement 的进一步处理,并且控制权会传递到 EXCEPTION 部分。会在 WHEN 子句中搜索与所发生错误相匹配的第一个异常。 如果找到匹配项,那么将执行相应的 处理语句 并将控制权传递到 END 之后的语句。如果找不到匹配项,那么程序将停止执行。
如果执行 处理语句 时发生新的错误,那么它只能由外层的 EXCEPTION 子句捕获。
WHEN 子句中的异常可以是用户定义的,也可以是系统定义的。可在当前块或其外层块的 DECLARE 部分中定义用户定义的异常,也可在 PL/SQL 程序包的 DECLARE 部分中定义用户定义的异常。可在异常定义后面直接使用语法 PRAGMA EXCEPTION_INIT 或 PRAGMA DB2_EXCEPTION_INIT,从而指定与用户定义的异常对应的 Oracle sqlcode 或 DB2 sqlstate。
DECLARE
exception1 EXCEPTION;
exception2 EXCEPTION;
PRAGMA EXCEPTION_INIT(exception2,-942);
exception3 EXCEPTION;
PRAGMA DB2_EXCEPTION_INIT(exception3,'42601');
BEGIN
MyApp.Main(100);
EXCEPTION
WHEN exception1 THEN
DBMS_OUTPUT.PUT_LINE('User-defined exception1 caught');
WHEN exception2 THEN
DBMS_OUTPUT.PUT_LINE('User-defined exception2 (Undefined name) caught');
WHEN exception3 THEN
DBMS_OUTPUT.PUT_LINE('User-defined exception3 (Syntax error) caught');
END
当捕获了使用 PRAGMA EXCEPTION_INIT 初始化的异常时,由 SQLCODE 函数返回的值是与该异常相关联的 DB2 sqlcode,而不是 Oracle 值。在以上示例中,当捕获了 exception2 时,由 SQLCODE 返回的值将为 -204,它是与 Oracle sqlcode -942 对应的 DB2 sqlcode。如果 Oracle-DB2 错误映射表中未列示在 PRAGMA EXCEPTION_INIT 中指定的 Oracle sqlcode,那么编译失败。可通过执行下列操作来避免发生此情况:将 PRAGMA EXCEPTION_INIT 替换为 PRAGMA DB2_EXCEPTION_INIT,并且指定与要识别的错误对应的 DB2 sqlstate。
| 异常名称 | 描述 |
|---|---|
| CASE_NOT_FOUND | 在 CASE 语句中,没有任何情况求值为“true”,并且没有 ELSE 条件。 |
| CURSOR_ALREADY_OPEN | 试图打开已打开的游标。 |
| DUP_VAL_ON_INDEX | 索引键有重复的值。 |
| INVALID_CURSOR | 试图访问未打开的游标。 |
| INVALID_NUMBER | 数字值无效。 |
| LOGIN_DENIED | 用户名或密码无效。 |
| NO_DATA_FOUND | 没有满足选择标准的行。 |
| NOT_LOGGED_ON | 不存在数据库连接。 |
| OTHERS | 表示任何未被异常节中的先前条件捕获的异常。 |
| SUBSCRIPT_BEYOND_COUNT | 数组下标超出范围或不存在。 |
| SUBSCRIPT_OUTSIDE_LIMIT | 数组下标表达式的数据类型无法指定给数组下标类型。 |
| TOO_MANY_ROWS | 多行满足选择标准,但只允许返回一行。 |
| VALUE_ERROR | 值无效。 |
| ZERO_DIVIDE | 试图除零。 |