所有DML的其他异常处理时我需要吗?

And*_*tin 1 sql oracle plsql exception-handling

我对在Oracle中处理未知异常的最佳实践感到困惑.

我可以这样做:

BEGIN
    --do something
EXCEPTION
WHEN NO_DATA_FOUND THEN
    raise_application_error etc
WHEN OTHERS THEN
    raise;
END;
Run Code Online (Sandbox Code Playgroud)

这似乎是在一些博客和网站上推荐的,甚至在Oracle文档中也有讨论:

通过在每个PL/SQL程序的顶层包含OTHERS异常处理程序来避免未处理的异常.

使OTHERS异常处理程序中的最后一个语句成为RAISE或调用RAISE_APPLICATION_ERROR过程.(如果您不遵循此惯例,并且启用了PL/SQL警告,那么您将获得PLW-06009.)有关RAISE或调用RAISE_APPLICATION_ERROR的信息,请参阅"显式提升异常".

但是我也知道在一些地方已经提到这是相当可怕的,例如Ask Tom:

我真的希望我们甚至不支持其他人.

您应该只捕获您期望的异常并且可以做些什么.让其他人传播出来,这样你就可以发现它们(所以你看到它们)

所以我的问题很简单:

我是否需要一个其他的子句来记录和提升每一个,我有一些时间使用数据操作语言(例如插入/更新/删除)?如果没有,我什么时候想避开它?

Jus*_*ave 6

与任何事情一样,这取决于.

通常,我的偏见是只捕获您可以处理的那些异常,或者您可以添加其他信息/上下文.例如,如果您知道SELECT INTO可能返回0行,no_data_found则可以提供合理的默认值并继续运行,从而处理异常是有意义的.如果您可以向异常添加其他上下文,通常是通过使错误消息的文本更有意义("找不到客户"而不是"找不到数据")或者通过包含诸如本地变量的值之类的内容来提供帮助用于调试.

设计代码可能是有意义的,这样你总是有一个WHEN OTHERS异常处理程序可以捕获意外异常,将它们与适当的上下文(例如局部变量的值)一起记录到表(或文件)中,然后重新抛出他们.如果你一直这样做,你最终会得到一些非常详细的错误记录,它会在抛出意外异常时提供有关程序状态的大量信息.不幸的是,在绝大多数情况下,实施和维护这些系统的团队在整个过程中都会失去他们的纪律,并且WHEN OTHERS导致使用导致远不那么可维护的系统.

如果你有一个WHEN OTHERS不以RAISE(或RAISE_APPLICATION_ERROR)结尾的泛型,你的代码将默默地吞下异常.来电者不会知道出了什么问题,并且会继续认为一切都好.但是,不可避免的是,未来的某些步骤将失败,因为较早的静默故障使系统处于意外状态.如果你有一个WHEN OTHERS大块的末尾有几十个SQL语句而只是一个泛型RAISE,你将丢失有关实际错误发生在哪一行的信息.