【问题标题】:In PL/SQL (Oracle), can exceptions propagate across function/procedure calls?在 PL/SQL (Oracle) 中,异常可以跨函数/过程调用传播吗?
【发布时间】:2012-03-04 17:57:04
【问题描述】:

因为它发生在封闭的块中
如果匿名块调用引发异常的函数,则这些异常既不会显示在控制台上,也不会被困在封闭块中...
更重要的是,在函数中被handler捕获后,匿名块中函数调用后的行正常执行!

被调用的程序是:

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;

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

【问题讨论】:

  • '在被函数中的处理程序捕获后'...如果异常被捕获,那么它将不会被传播,除非捕获器重新引发它。听起来捕手可能正在使用dbms_output 来“报告”错误,在这种情况下,您需要set serveroutput on 才能看到它。您确实需要显示函数和匿名块代码以获得任何明智的帮助,否则我们只能猜测正在发生的事情以及您想要/期望发生的事情。

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


【解决方案1】:

如果异常被函数中的处理程序捕获并且没有重新引发,那么调用者将不会触发异常。这是正确的行为。如果您希望调用者可以看到异常,则必须在函数中使用RAISE 命令重新引发它:

FUNCTION fun ...
...
EXCEPTION
  WHEN some_exception THEN
    ...
    RAISE;
END;

或者,您可以引发不同的异常,例如

EXCEPTION
  WHEN some_exception THEN
    ...
    RAISE_APPLICATION_ERROR(-20001,'My error message');
END;

【讨论】:

  • @pop stack:我认为你的问题不清楚。它说“在被函数中的处理程序捕获后”。该处理程序实际上做了什么 - 你能显示代码吗?
  • 现在我们可以看到您的代码,Dave Costa 的回答更加相关。没有引发异常。
【解决方案2】:

在您的具体示例中,我认为根本没有提出任何例外。您说“在产品编号无效的情况下”,我假设您的意思是产品编号不存在。听起来您希望查询抛出 NO_DATA_FOUND,但由于它使用的是没有 GROUP BY 的聚合函数,因此如果没有匹配的行,它实际上会返回包含 NULL 的单行。

【讨论】:

    【解决方案3】:

    只是为了补充托尼的答案。 你可能不知道调用函数可能抛出什么类型的异常。在这种情况下,您可以这样做:

    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;
    

    【讨论】:

    • 这不是多余的吗?无论如何,您没有明确捕获的任何内容都会冒泡给调用者?
    • 是的,不过只是为了说明错误处理中“当别人”的原则。
    猜你喜欢
    • 2016-09-28
    • 1970-01-01
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 2010-09-18
    • 1970-01-01
    相关资源
    最近更新 更多