我对PL / SQL还是很陌生,并且正在尝试为我编写的程序包实现一些异常处理。
我遇到了可能会引发多个异常的情况。
在引发这些异常的情况下,我可能想针对每个异常进行特定的操作,例如,如果引发异常A,则关闭并删除文件,但是如果引发异常B,则只需要关闭游标并发送电子邮件以警告某人发生致命错误。
这很好,我了解如何使用WHEN <EXCEPTION_NAME> THEN
。
我遇到的问题是,我无法编写针对任何异常而发生的通用代码,以在发生异常的情况下执行我一直希望做的事情,例如写入日志文件。这意味着我必须为每种异常类型复制代码行,如下所示。
DECLARE
test_exception EXCEPTION;
BEGIN
--some code
RAISE test_exception;
--some code
EXCEPTION
WHEN test_exception THEN
SEND_EMAIL('Something went wrong');
WRITE_TO_LOG('Error ' || SQLCODE || ' | ' || SUBSTR(SQLERRM, 1, 200) || ' | ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
WHEN OTHERS THEN
SOME_OTHER_FUNCTION();
WRITE_TO_LOG('Error ' || SQLCODE || ' | ' || SUBSTR(SQLERRM, 1, 200) || ' | ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
END;
我想要实现的是与此类似的东西,无法编译。
DECLARE
test_exception EXCEPTION;
BEGIN
--some code
RAISE test_exception;
--some code
EXCEPTION
WRITE_TO_LOG('Error ' || SQLCODE || ' | ' || SUBSTR(SQLERRM, 1, 200) || ' | ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
WHEN test_exception THEN
SEND_EMAIL('Something went wrong');
WHEN OTHERS THEN
SOME_OTHER_FUNCTION();
END;
很显然,这个示例并不完整,但是给出了一个大概的想法。对于这样的一条重复的行来说,这不是问题,但是如果要关闭许多游标或文件或进行其他内务处理,这似乎有些冗长/乏味。
是否有WHEN ALL THEN
子句或类似的子句?这是某种GOTO
的用例吗?还是我在这里尝试应用错误的概念。
我似乎找不到有人问同样的问题,对我来说,这意味着我以错误的方式来解决这个问题,或者我缺少一些基本知识。
谢谢
答案 0 :(得分:3)
PL / SQL将仅执行一个异常块。因此,如果您要针对每个异常运行一些通用代码(例如,日志记录),则必须在when others
中执行。
然后检查sqlcode
进行特定于异常的处理。例如:
begin
raise TOO_MANY_ROWS;
exception
when others then
dbms_output.put_line ( 'Generic stuff' );
case sqlcode
when -1422 then
dbms_output.put_line ( 'TMR specific' );
when -1476 then
dbms_output.put_line ( 'ZD specific' );
else
null;
end case;
raise;
end;
/
Generic stuff
TMR specific
ORA-01422: exact fetch returns more than requested number of rows
begin
raise ZERO_DIVIDE;
exception
when others then
dbms_output.put_line ( 'Generic stuff' );
case sqlcode
when -1422 then
dbms_output.put_line ( 'TMR specific' );
when -1476 then
dbms_output.put_line ( 'ZD specific' );
else
null;
end case;
raise;
end;
/
Generic stuff
ZD specific
ORA-01476: divisor is equal to zero
现在,这是否是一个好的想法尚待商.。
when others
异常块应以某种方式重新引发异常。这可以防止您抑制严重的意外错误(例如磁盘空间不足)。但是对于某些特定的例外情况,您可能需要进行处理。
附录
如果您有用户定义的异常,则需要通过魔杖来处理这些异常。一种方法是创建一个标准异常包。在其中,为将要使用的所有异常命名,初始化和定义值常量。
然后您可以将这些定义用于用户定义的异常:
create or replace package excepts as
user_defined exception ;
user_defined_val pls_integer := -20001;
pragma exception_init ( user_defined, -20001 );
end;
/
begin
raise excepts.USER_DEFINED;
exception
when others then
dbms_output.put_line ( 'Generic stuff' );
case sqlcode
when -1422 then
dbms_output.put_line ( 'TMR specific' );
when -1476 then
dbms_output.put_line ( 'ZD specific' );
when excepts.user_defined_val then
dbms_output.put_line ( 'User-defined specific' );
else
null;
end case;
raise;
end;
/
Generic stuff
User-defined specific
ORA-20001:
答案 1 :(得分:0)
如果我不能正确理解-解决方案非常简单。引发异常时,可以在嵌套块中处理它,并通过RAISE
DECLARE
test_exception EXCEPTION;
begin
RAISE test_exception;
--some code
EXCEPTION
WHEN OTHERS THEN
BEGIN
dbms_output.put_line( 'WRITE_TO_LOG');
RAISE;
EXCEPTION
WHEN test_exception THEN
dbms_output.put_line( 'test_exception');
WHEN OTHERS THEN
dbms_output.put_line( 'some other function');
end;
END;
输出:
WRITE_TO_LOG
send mail