因为它发生在封闭的块中 如果一个匿名块调用一个引发异常的函数,那么它们既不会显示在控制台上也不会被困在封闭的块中...... 更重要的是,在被函数中的处理程序捕获之后,匿名块中的函数调用之后的行正常执行!
被叫程序是:
CREATE OR REPLACE PROCEDURE qt(pno number, qty OUT number)
IS
BEGIN
select sum(qty_on_hand) into qty from products where productno=pno;
END;
调用块是:
DECLARE
qty number;
BEGIN
qt(&pno, qty);
dbms_output.put_line('qty is: '||qty);
END;
如果产品编号无效,则不会显示错误;为什么呢?
答案 0 :(得分:8)
如果函数中的处理程序捕获到异常而未重新引发,则调用者不会触发任何异常。这是正确的行为。如果您希望调用程序可以看到异常,则必须使用RAISE
命令在函数中重新引发它:
FUNCTION fun ...
...
EXCEPTION
WHEN some_exception THEN
...
RAISE;
END;
或者你可以提出另一个例外,例如
EXCEPTION
WHEN some_exception THEN
...
RAISE_APPLICATION_ERROR(-20001,'My error message');
END;
答案 1 :(得分:6)
在您的具体示例中,我认为根本没有例外。您说“如果产品编号无效”,我认为您的意思是产品编号不存在。听起来你希望你的查询抛出NO_DATA_FOUND,但由于它使用的是没有GROUP BY的聚合函数,如果没有匹配的行,它实际上将返回包含NULL
的单行。
答案 2 :(得分:0)
只是为了补充Tony的答案。 您可能不知道调用函数可能抛出的异常类型。在这种情况下,你可以这样做:
EXCEPTION
WHEN exception_that_may_occur_in_my_function THEN
...
RAISE_APPLICATION_ERROR(-20001,'My error message');
WHEN others THEN -- Any exception that can come from a function I'm calling
RAISE;
END;