Pl / SQL嵌套过程异常处理

时间:2014-11-13 15:13:54

标签: oracle stored-procedures plsql exception-handling

这是关于通过多级PL / SQL过程进行错误处理的最佳实践问题。我已经看了几个其他问题来帮助我,特别是this one

目前,我有一个程序1,程序1调用程序2,调用程序3.我试图执行足够的错误处理 - 但我想最终将确切的问题输出回应用层。我希望能够有效而清晰地了解如何做到这一点。

我目前的解决方法如下,但对我来说似乎相当混乱,有很多变量声明。我是PL / SQL(以及一般的SQL)的新手,所以我很感激任何建议:

  1. 处理多层程序时的良好错误处理技术。
  2. 将错误消息反馈到应用程序层(在我的程序中,由" out_overall_output"变量表示。
  3. 计划流程:用户界面 - > Proc 1 - > Proc 2 - > Proc 3

    程序1:

    --One input variable, one output.
    in_id                VARCHAR2;
    out_overall_output   VARCHAR2;
    ...
    DECLARE
        l_success         BOOLEAN;
        l_error_output    VARCHAR2(100);
    BEGIN
        Proc2(id, l_success, l_error_output);
        IF l_success = FALSE THEN
            out_overall_output = l_error_output
        END IF
    EXCEPTION
    WHEN OTHERS THEN
        ROLLBACK;
        out_overall_output:= 'Error calling Proc 2'
        RETURN;
    END;
    --Normal flow continues if l_success is true...
    

    程序2:

    -- One input variable, two output.
    in_id
    out_success
    out_error_output
    //other logic
    DECLARE
        l_success         BOOLEAN;
        l_error_output    VARCHAR2(100)
    BEGIN
        Proc3(id, l_success, l_error_output)
        IF l_success = FALSE THEN
            out_error_output = l_error_output
        END IF
    EXCEPTION
    WHEN OTHERS
        out_error_output = 'Error calling Proc 3'
        RETURN;
    END;
    

    程序3:

    --One input variable, two output.
    in_id                VARCHAR2;
    out_success          BOOLEAN;
    out_error_message    VARCHAR2;
    ...
    BEGIN
        DELETE 
        FROM table
        WHERE id = in_id;
    EXCEPTION
    WHEN NO_DATA_FOUND THEN
        out_success = FALSE;
        out_error_message = 'Error - No data to delete'
    WHEN OTHERS THEN
        out_success = FALSE;
        out_error_message = 'Error deleting data.'
    END;
    

    注意:程序调用的级别比这更深。我所展示的片段大大简化了。我的实际过程中的错误消息和变量名称更具描述性。

1 个答案:

答案 0 :(得分:2)

要显示应用程序级别“服务器会发生什么”的确切说明,您可以尝试以下操作。在程序中:

create or replace procedure p1 is
...
exception
  when <some_error> then
    <do something>
    -- re-raise error:
    raise_application_error(-20001, 'Client with ID '|| ID || ' has no right to perform action "' || ACTION_NAME || '"', true);
end;

create or replace procedure p2 is
begin
  p1;
exception
  when <another_error> then
    <do something>
    -- re-raise error:
    raise_application_error(-20002, 'Action "' || ACTION_NAME || '" is not completed', true);
end;

create or replace procedure p3 is
begin
  p2;
exception
  when <another_error> then
    <do something>
    -- re-raise error:
    raise_application_error(-20003, 'Purchasing of "' || CAR_NAME || '" cancelled', true);
end;

在顶级程序中:

create or replace procedure top_level_procedure is
begin
  p1;
exception
  when <one_more_error> then
    <do something>
    raise_application_error(-20004, dbms_utility.format_error_backtrace);
end;

p1中出现异常后,您会看到以下内容:

ORA-20003: Purchasing of "Cool red Ferrari" cancelled
ORA-20002: Action "car purchase" is not completed
ORA-20001: Client with ID 123 has no right to perform action "Spent all money of Bill Gates"

具有raise_application_error值的过程false的第三个参数会删除所有先前的错误消息。如果您在过程p3中使用false值,则在此示例中只会看到一条代码为ORA-20003的错误消息。

P上。 S.此外,您可以定义自己的异常并在WHEN .. THEN子句中使用它们。您可以在此处找到更多信息和示例:https://docs.oracle.com/cd/B28359_01/appdev.111/b28370/errors.htm#LNPLS00704

P上。 P. S.如何记录。记录程序:

create or replace procedure log(p_log_message varchar2) is
pragma autonomous_transaction;
begin
  insert into log_table(..., log_message) values (..., p_log_message);
  commit;
end;

通话记录程序:

  when <one_more_error> then
    <do something>
    log(..., dbms_utility.format_error_backtrace);
    raise_application_error(-20004, dbms_utility.format_error_backtrace);