异常处理 (PL/SQL)
缺省情况下,在 PL/SQL 程序中遇到的任何错误都将停止执行程序。您可以使用 EXCEPTION 节来捕获错误以及从出错状态恢复。
异常处理程序的语法是 BEGIN 块的语法扩展。
语法
如果未发生错误,那么此块仅仅执行 statement 并将控制权传递到 END 之后的语句。但是,如果在执行 statement 时发生错误,那么会放弃对 statement 的进一步处理,并且控制权会传递到 EXCEPTION 部分。会在 WHEN 子句中搜索与所发生错误相匹配的第一个异常。 如果找到匹配项,那么将执行相应的 处理语句 并将控制权传递到 END 之后的语句。如果找不到匹配项,那么程序将停止执行。
如果执行 处理语句 时发生新的错误,那么它只能由外层的 EXCEPTION 子句捕获。
WHEN 子句中的异常可以是用户定义的,也可以是内置的。可在当前块或其外层块的 DECLARE 部分中定义用户定义的异常,也可在 PL/SQL 程序包的 DECLARE 部分中定义用户定义的异常。可在异常定义后面直接使用语法 PRAGMA EXCEPTION_INIT 或 PRAGMA DB2_EXCEPTION_INIT,从而指定与用户定义的异常对应的 sqlcode 或 sqlstate。
MyApp.Main
的调用。EXCEPTION 部分包含用于下列三个异常的处理程序:exception1,与 sqlcode 或 sqlstate 不相关联。exception2,与 sqlcode -942(未定义名称)相关联。exception3,与 sqlstate 42601(语法错误)相关联。
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 函数返回的值是与该异常相关联的
sqlcode,而不是 Oracle 值。在以上示例中,当捕获了 exception2
时,由 SQLCODE 返回的值将为 -204,它是与 Oracle sqlcode -942 对应的 sqlcode。如果
Oracle- 错误映射表中未列示在 PRAGMA EXCEPTION_INIT 中指定的 Oracle sqlcode,那么编译失败。可通过执行下列操作来避免发生此情况:将
PRAGMA EXCEPTION_INIT 替换为 PRAGMA DB2_EXCEPTION_INIT,并且指定与要识别的错误对应的 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 | 试图除零。 |
