【发布时间】:2015-01-18 09:31:27
【问题描述】:
背景:
我使用了几篇 Oracle 文章开发了一个错误包,它由五个过程组成。
其中两个是 Log_And_Return 和 Log_And_Continue。它们在整个程序中被调用。每个都接受输入并将其传递给 Handle 过程。例如:
PROCEDURE Log_And_Return (error_name)
IS
BEGIN
Handle (error_name, TRUE, TRUE);
END Log_And_Return;
Handle 过程然后根据传递给它的变量调用 Log 过程和 Raise_To_Application 过程,如下所示:
PROCEDURE Handle (error_name, log_error, reraise_error)
IS
BEGIN
// Code to fetch error code and message using error_name input parameter.
IF log_error THEN
LOG (error_code, error_message);
END IF;
IF in_reraise_error THEN
Raise_To_Application (error_code, error_message);
END IF;
END Handle;
日志过程存储日期、堆栈跟踪、错误代码、错误消息和 id,最后 Raise_To_Application 过程执行所说的:
raise_application_error (error_code, error_message);
问题:
我的问题是这个。假设我有一个执行查询的程序,例如获取客户记录。如果这个查询失败,这是一个大问题。所以我可以这样做:
BEGIN
SELECT *something*
FROM *some table*
WHERE *some field* = *some user input*
// more logic
EXCEPTION
WHEN NO_DATA_FOUND THEN
ERR.Log_And_Return('unknown_id');
WHEN OTHERS THEN
ERR.Log_And_Return('unknown_error');
END;
在这里,我的 Log_And_Return 过程接受输入,转到表格并返回一个字符串以显示给用户。如果查询没有找到用户的记录,我有一个特定的错误,而对于未知错误,我有一个通用错误。在这两种情况下,都会执行日志记录以获取错误的完整堆栈跟踪。
但是,在我的示例中,我有一个“// 更多逻辑”部分。假设,我将代码修改为:
BEGIN
SELECT *something* INTO *some variable*
FROM *some table*
WHERE *some field* = *user id*
Call_Another_Procedure(*user id*, *some variable*)
EXCEPTION
WHEN NO_DATA_FOUND THEN
ERR.Log_And_Return('unknown_id');
WHEN OTHERS THEN
ERR.Log_And_Return('unknown_error');
END;
现在,在选择查询之后,我正在使用选择查询的结果调用另一个过程。在这个 new 查询中,我做了一些事情,包括一个 update 语句,如下所示:
// bunch of logic
BEGIN
UPDATE *another table*
SET *some field* = *some value*
WHERE *some field* = *variable passed into method*
EXCEPTION
WHEN NO_DATA_FOUND THEN
Err.Log_And_Return('some_error')
END;
问题:
我的问题是,如果查询未返回任何结果,我会抛出 NO_DATA_FOUND 错误,我会记录问题,然后在“Raise_To_Application”过程中引发应用程序错误......然后被父过程中的“当其他人”子句捕获,这将向用户返回错误消息。
解决方法是什么? 注意:如果需要发布更多代码,请告诉我。
编辑:
我考虑过的一种解决方法,但我不知道是否推荐这样做,就是用 BEGIN END EXCEPTION 块包装每个存储过程,其中每个过程都有一个刚刚记录的“When Others”块和重新引发了最近的错误(即使用 SQLCODE)。然后,在我的应用程序层中,我可以指定如果错误在 -20000 和 -20999 之间,则将其与消息一起显示,否则显示一般消息(DBA 可以通过查看日志来找出数据库中发生的情况表,以及完整的堆栈跟踪)。对此有什么想法吗?
编辑 2:
如果有什么不明白的地方,我可以澄清一下。我对代码进行了大量更改和简化,以删除 id 参数和其他一些内容。
【问题讨论】:
-
这是dba.stackexchange.com/q/83163/6260 的多帖子(又名交叉帖子)。请勿多发:meta.stackexchange.com/q/64068
标签: oracle exception stored-procedures plsql