异常与Oracle错误的关联可通过EXCEPTION_INIT编译器指令实现。语法:
PRAGMA EXCEPTION_INIT(exception_name , oracle_error_number);
(在PL/SQL中使用编译器指令的语法都是以pragma打头,且只能在代码的声明部分使用。可参照自治事务的用法)
1>被关联的异常只能是用户自定义的异常,不能是预定义的异常名。当然用户可定义一个与预定义同名的异常(但不提倡这样做);
2>一个错误可以关联多个异常,关联同一个错误的异常不能在异常处理部分同时出现;
5、SQLCODE返回的是当前的错误号。
SQLERRM返回的是当前的错误信息文本。
如果错误(异常)是通过RAISE显式引发的用户自定义异常,且该异常没有通过EXCEPTION_INIT语句与错误代号进行关联,则SQLCODE返回值为1,而SQLERRM返回的信息是:ORA-06510: PL/SQL: unhandled user-defined exception。
也可以这样理解:用户自定义的异常默认与错误代号为1的错误进行关联,而错误代号为1的错误信息文本是:ORA-06510: PL/SQL: unhandled user-defined exception。
两个相关例子:
SQL> DECLARE
2 e_test EXCEPTION;
3 BEGIN
4 RAISE e_test;
5 EXCEPTION WHEN OTHERS THEN
6 DBMS_OUTPUT.PUT_LINE(SQLCODE);
7 DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.FORMAT_ERROR_STACK);
8 END;
9 /
1
ORA-06510: PL/SQL: unhandled user-defined exception
PL/SQL过程已成功完成。
SQL> DECLARE
2 e_test EXCEPTION;
3 PRAGMA EXCEPTION_INIT(e_test ,-20001);
4 BEGIN
5 RAISE_APPLICATION_ERROR(-20001,'This is a test.');
6 EXCEPTION
7 WHEN e_test THEN
8 DBMS_OUTPUT.PUT_LINE(SQLCODE);
9 DBMS_OUTPUT.PUT_LINE(SQLERRM);
10 WHEN OTHERS THEN
11 NULL;
12 END;
13 /
-20001
ORA-20001: This is a test.
PL/SQL过程已成功完成。
6、使用RAISE_APPLICATION_ERROR方法引发异常并创建错误代号与错误消息。语法:
RAISE_APPLICATION_ERROR(error_number,error_message[,keep_errors]);
其中,error_number是在-20000到-20999之间的一个值。error_message是与该错误关联的文本.keep_errors的值为TRUE或FALSE,如为TRUE,新产生的错误就会追加到已引发错误的列表中(如果已经有错误的话)。如为FALSE(FALSE也是默认值),新发生的错误就会替换当前的错误列表。
SQL> BEGIN
2 BEGIN
3 BEGIN
4 RAISE_APPLICATION_ERROR(-20001,'This is a test.',TRUE);
5 EXCEPTION WHEN OTHERS THEN
6 RAISE_APPLICATION_ERROR(-20002,'I raised by 20001.',TRUE);
7 END;
8 EXCEPTION WHEN OTHERS THEN
9 RAISE_APPLICATION_ERROR(-20003,'I raised by 20002.',TRUE);
10 END;
11 EXCEPTION WHEN OTHERS THEN
12 DBMS_OUTPUT.PUT_LINE(SQLCODE);
13 DBMS_OUTPUT.PUT_LINE(SQLERRM);
14 END;
15 /
-20003
ORA-20003: I raised by 20002.
ORA-20002: I raised by 20001.
ORA-20001: This is a test.
PL/SQL过程已成功完成。
7、异常的传播
1、声明部分和异常部分引发的异常都会立即传播到该封装块。
2、使用不带任何参数的RAISE语句,再次引发当前异常。该语句只能在异常处理部分出现,通常是为了异常能从已被捕获的处理块中再次传出。
8、异常与事务
引发异常不会结束某个事务,就像终止某个代码块不会终止一个事务一样。
但是如果顶层的代码块以一个未处理异常而终止,该异常就会传播到调用环境,代码中产生的相应事务就会立即由服务器进行回滚。
9、异常可当作控制语句使用(如跳过某段程序的执行、终止整个程序的执行等)。