pl/sql 中的错误处理
Posted
技术标签:
【中文标题】pl/sql 中的错误处理【英文标题】:Error handling in pl/sql 【发布时间】:2010-06-28 15:50:25 【问题描述】:我想了解 PL/SQL 中的错误处理。谁能帮我找到有关此主题的简要说明?
【问题讨论】:
【参考方案1】:每个块都可以有一个异常处理程序。示例:
DECLARE
/* declare your variables */
BEGIN
/*Here is your code */
EXCEPTION
WHEN NO_DATA_FOUND THEN
/* HAndle an error that gets raised when a query returns nothing */
WHEN TOO_MANY_ROWS THEN
/* HAndle the situation when too much data is returned such as with a select-into */
WHEN OTHERS THEN
/* Handle everything else*/
END;
这个链接会告诉你更多:http://download.oracle.com/docs/cd/B13789_01/appdev.101/b10807/07_errs.htm
该链接将向您显示比我更详细的信息,以及有关如何创建自己的异常名称的示例。
总是让我感到困惑的一点是,如果你有一个函数并且你没有在异常处理程序中返回一个值,那么调用函数中就会抛出一个异常。没什么大不了的,但我似乎总是忘记那个。
【讨论】:
如果一个异常没有在较低的块中被捕获,它会被传播到更高的块(并最终传播到客户端)。旧规则适用 - 永远不要检查您不知道如何处理的错误情况。让它向上流动。更高级别的块将捕获它,或者调用将失败并且客户端应用程序(或用户)将处理它。【参考方案2】:另一个答案中引用的 Oracle 文章非常值得一读。
需要添加一些额外的东西 - 捕获 PL/SQL 异常会丢失错误堆栈 - 即关于哪一行引发异常的确切信息。
这会使调试包含可能引发相同异常的多个位置的代码块变得困难(即,如果您有多个可能返回 NO_DATA_FOUND 的 SQL 语句)。这里的一种选择是将完整的错误堆栈记录为异常处理程序的一部分。
EXCEPTION
WHEN TOO_MANY_ROWS THEN
myLogger('Some useful information',DBMS_UTILITY.FORMAT_ERROR_STACK);
END;
如果您确实需要捕获异常,请将您的异常处理尽可能本地化到您想要捕获的位置,并且仅在万不得已时才使用 WHEN OTHERS。
您也可以“做某事并重新引发相同的异常”
EXCEPTION
WHEN TOO_MANY_ROWS THEN
closeSmtpConnection;
RAISE;
END;
最有用的功能之一是命名和捕获 Oracle SQL 内部异常的能力。
DECLARE
recompile_failed EXCEPTION;
PRAGMA EXCEPTION_INIT (recompile_failed,-24344);
BEGIN
. . . . . .
EXCEPTION
WHEN recompile_failed THEN
emailErrors(pObjectType,pObjectName);
END;
另一方面是能够引发用户定义的“SQL”异常
RAISE_APPLICATION_ERROR(-20001,'my text')
这是将用户定义的文本传播到调用应用程序的唯一方法,因为用户定义的 pl/sql 异常不会跨越“范围”边界。
不幸的是,尽管文档说 -20000 到 -20999 范围可用于用户定义的异常,但某些 Oracle 扩展包使用这些序列号,因此您不能仅依靠序列号来识别调用语言中的错误.
(大多数人倾向于将 RAISE_APPLICATION_ERROR 包装在其他代码中以记录错误,并且通常从表中导出错误文本)
我发现一个有用的技巧是在包体中创建一个包含“有状态”变量的包,以及简单的 setter 和 getter 函数。与数据库更新不同,包中的信息不会因错误而回滚。
在发生错误时,在包中设置信息,然后使用调用语言中的 getter 检索它,以构造“本机”异常。
至于用户定义的 pl/sql 异常 - 这些在本地代码中可能很有用,但在许多情况下,可以通过使用不同的控制结构来避免它们(即避免将它们用作替代 GOTO)。
在包头上创建全局异常,以指定包可能返回的可能异常似乎是个好主意,但最终结果是您的调用代码最终不得不处理可能在任何底层软件包。
我自己过去曾走这条路,现在我建议不要这样做 - 使包自包含并使用 RAISE_APPLICATION_ERROR 或将错误作为文本传回。
【讨论】:
以上是关于pl/sql 中的错误处理的主要内容,如果未能解决你的问题,请参考以下文章