PL/SQL包级别的异常处理

4
我有一个简单的问题:包级别是否可以进行异常处理?如果可以,要如何实现?
我的包中有许多过程和函数,如果出现了例如NO_DATA_FOUND等异常情况,我希望在所有的过程和函数中都能做同样的事情。
因此我的问题是:我可以这样写吗?
WHEN NO_DATA_FOUND THEN

我只需要在所有的过程/函数中使用相同的行来处理NO_DATA_FOUND异常,还是我必须在每个过程/函数中编写异常处理程序?
3个回答

6
抱歉,您无法在包中全局处理所有过程/函数的异常。 异常处理程序文档 表示:
“异常处理程序处理引发的异常。异常处理程序出现在匿名块、子程序、触发器和包的异常处理部分中。”
这使得它听起来好像可以; 但是,“包”参考的是 create package body 语句 的初始化部分:

enter image description here

但是这个部分"初始化变量并执行任何其他一次性设置步骤",在每次会话时运行一次,当包中的函数或过程首次被调用时。它的异常处理程序不会做任何其他事情。

如果你真的想要类似的行为,那么你可以将其放入自己的(可能是私有的)过程中,并在每个过程/函数的异常处理程序中调用它。这可能会节省一些打字,但如果你试图记录错误,那么很可能掩盖了实际发生的情况。即使这会导致一些重复,具体的异常处理也可能更简单更好。


4
不可能。我认为语言中没有这个功能是因为它与异常处理程序的正确和预期使用不一致。
我的经验法则是:“如果你没有特定有用的响应异常的内容,就不要捕获它。”
如果在特定情况下可以忽略NO_DATA_FOUND并假定数据的默认值,则需要捕获并处理它。在所有其他情况下,您不希望捕获NO_DATA_FOUND - 它代表真正的异常:某些超出您设计假设之外的事情。将它们传播到最高层级,以便记录并/或向客户报告。
但是,如果您解释一下希望包级别异常处理程序执行什么操作,也许会得到更好的答案。

我同意你的看法,已经有了查询级别的异常,这些异常是有很好的理由存在的,比如给变量赋值等。包级别的异常只是为了记录日志,虽然很复杂难以解释,但我无法在更高的级别上记录异常,所以我必须在这个包内部处理。感谢你的回答。 - BeRightBack

4
一个包不是可执行对象,因此无法处理包中的过程和函数引发的异常。您需要在生成异常的地方处理异常。
似乎有点不太可能每次抛出特定异常时都要做完全相同的事情。通常,您希望异常处理程序尽可能接近生成错误的代码,以便获得最大量的上下文信息。通常,这意味着在单个过程中具有多个异常处理程序。
PROCEDURE p1 
AS
  ...
BEGIN
  BEGIN
    SELECT col1
      INTO l_var1
      FROM some_table
     WHERE <<something>>
  EXCEPTION
    WHEN no_data_found
    THEN
      l_var1 := null;
  END;

  <<do something>>

  BEGIN
    SELECT col2
      INTO l_var2
      FROM some_table2
     WHERE <<something>>
  EXCEPTION
    WHEN no_data_found
    THEN
      raise_application_error( -20001, 'Error, cannot find a row in some_table2' );
  END;

  ...
END;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接