这是我经常被问到的一个问题。由于我在stackoverflow上找不到任何完全重复,我想我会把它作为参考发布。
问题: 在PL / SQL中,我知道如何捕获异常并在捕获它们时执行代码,以及如何将它们传播到调用块。 例如,在以下过程中,直接处理NO_DATA_FOUND异常,而所有其他异常都引发到调用块:
CREATE OR REPLACE PROCEDURE MY_PROCEDURE()
IS
BEGIN
do_stuff();
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- Do something
handle_exception();
WHEN OTHERS THEN
-- Propagate exception
RAISE;
END;
但是我应该使用什么命令来忽略一个或所有引发的异常并将执行控制返回给调用块?
答案 0 :(得分:44)
虽然我同意99%的时间默默地忽略异常而不至少在某处记录异常是不好的做法,但在某些情况下这是完全可以接受的。
在这些情况下,NULL是你的朋友:
[...]
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
可能需要忽略异常的两种典型情况是:
1)您的代码包含一个您知道偶尔会失败的语句,并且您不希望这个事实中断您的程序流程。 在这种情况下,您应该将语句括在嵌套块中,如以下示例所示:
CREATE OR REPLACE PROCEDURE MY_PROCEDURE()
IS
l_empoyee_name EMPLOYEES.EMPLOYEE_NAME%TYPE;
BEGIN
-- Catch potential NO_DATA_FOUND exception and continue
BEGIN
SELECT EMPLOYEE_NAME
INTO l_empoyee_name
FROM EMPLOYEES
WHERE EMPLOYEE_ID = 12345;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
WHEN OTHERS THEN
RAISE;
END;
do_stuff();
EXCEPTION
WHEN OTHERS THEN
-- Propagate exception
RAISE;
END;
请注意,PL / SQL通常不允许从Visual Basic中获取On Error Resume Next类型的异常处理,其中忽略所有异常并且程序继续运行,就好像什么都没发生一样(参见On error resume next type of error handling in PL/SQL oracle) 。您需要在嵌套块中明确地包含可能失败的语句。
2)你的程序太不重要了,忽略它抛出的所有异常都不会影响你的主程序逻辑。 (但是,这种情况非常罕见,从长远来看通常会导致调试噩梦)
BEGIN
do_stuff();
EXCEPTION
WHEN OTHERS THEN
-- Ignore all exceptions and return control to calling block
NULL;
END;
答案 1 :(得分:2)
另一种情况是,默认忽略异常是有意义的: 当您调用期望创建对象的脚本(如果该对象不存在),并且您没有该对象的创建或替换语法时。 PLSQL对象具有创建或替换语法,但表和索引不具有。 然后我们可以将这些脚本放在一个块中并忽略引发的异常。