在PL / SQL(Oracle)中,异常可以跨函数/过程调用传播吗?

时间:2012-02-13 10:12:49

标签: oracle function stored-procedures exception-handling plsql

因为它发生在封闭的块中 如果一个匿名块调用一个引发异常的函数,那么它们既不会显示在控制台上也不会被困在封闭的块中...... 更重要的是,在被函数中的处理程序捕获之后,匿名块中的函数调用之后的行正常执行!

被叫程序是:

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;

如果产品编号无效,则不会显示错误;为什么呢?

3 个答案:

答案 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;