oracle - 当其他人然后异常处理

标签 oracle exception stored-procedures plsql

背景:

我已经用几篇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;

现在,在选择查询之后,我使用选择查询的结果调用另一个过程。在这个新查询中,我正在做一些事情,包括更新语句,如下所示:
// 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”过程中引发应用程序错误......然后将被“when others”子句捕获父过程,它将向用户返回错误消息。

解决方法是什么? 注意:如果需要发布更多代码,请告诉我。

编辑:

我考虑过的一种解决方法,我不知道是否推荐这样做,是将每个存储过程包装在 BEGIN END EXCEPTION 块中,其中每个过程都有一个“When Others”块,该块刚刚记录并重新引发最多最近的错误(即使用 SQLCODE)。然后,在我的应用程序层中,我可以指定如果错误在 -20000 和 -20999 之间,则将其与其消息一起显示,否则显示一条通用消息(DBA 可以通过查看日志找出数据库中发生的情况表,以及完整的堆栈跟踪)。对此有何想法?

编辑 2:

如果有什么不明白的,我可以澄清。我对代码进行了大量更改和简化,以删除诸如 id 参数之类的内容和其他一些内容。

最佳答案

这几乎是我一直在使用的方法,因为我想在我的代码中记录每个入口和导出点:

application_error EXCEPTION;
PRAGMA EXCEPTION_INIT (application_error, -20000);

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 application_error THEN -- ordinary exception raised by a subprocedure
    ERR.Log_And_Return('application_error');
    RAISE;
WHEN OTHERS THEN
    ERR.Log_And_Return('unknown_error');
    RAISE;
END;

对于子过程:
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');  -- this raises ORA-20000
END;

关于oracle - 当其他人然后异常处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27040996/

相关文章:

java - Oracle 不是有效的函数或过程名称

SQL 查询同时获取 group by 和不同的值

c# - try catch 的行为,最后在 c# 中使用 return 语句工作流程

c++ - vector 异常处理程序中的 EXCEPTION_ACCESS_VIOLATION 异常

vb.net - 使用 WebClient 处理 VB.NET SSIS 脚本中的异常(FTP 下载)

sql - 创建存储过程语法,与 GO 的使用相关

java.sql.SQLException : ORA-00942: table or view does not exist with JPA entityManager. createQuery()

sql - 我可以在 Oracle SQL 中嵌套 "WITH"子句吗?

html - 如何在 Oracle SQL*Plus HTML 报告中指定 HTML 文档类型?

java - 如何在调用存储过程时从前端设置 INOUT 参数