Oracle 异常处理 - 这是正确的吗?

发布于 2024-12-14 21:44:19 字数 588 浏览 2 评论 0原文

我有以下内容...

IF CONDITION1  THEN

        -- SELECT  STATEMENT MIGHT RETURN DATA

         IF CONDITION2 THEN

                -- SELECT COUNT

             IF CONDITION3 THEN



                    INSERT INTO TABLE
                            (
                            --- 
                            )
                    VALUES  (
                            ---
                            );


            End IF;


    END IF;


 END IF;


EXCEPTION
   WHEN NO_DATA_FOUND THEN
 RETURN;

END of Trigger

这是处理 CONDITION1 内 select 语句异常的正确方法吗?

I have the following...

IF CONDITION1  THEN

        -- SELECT  STATEMENT MIGHT RETURN DATA

         IF CONDITION2 THEN

                -- SELECT COUNT

             IF CONDITION3 THEN



                    INSERT INTO TABLE
                            (
                            --- 
                            )
                    VALUES  (
                            ---
                            );


            End IF;


    END IF;


 END IF;


EXCEPTION
   WHEN NO_DATA_FOUND THEN
 RETURN;

END of Trigger

Is this a correct way of handling exception for select statement inside CONDITION1?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烟酉 2024-12-21 21:44:19

PL/SQL 无法返回错误所在位置,因此您需要在要忽略特定错误的部分周围创建一个块:

IF CONDITION1  THEN
         BEGIN
         -- SELECT  STATEMENT MIGHT RETURN DATA
         EXCEPTION
             WHEN NO_DATA_FOUND THEN
                 NULL;
         END;
         IF CONDITION2 THEN
                -- SELECT COUNT
             IF CONDITION3 THEN
                    INSERT INTO TABLE
                            (
                            --- 
                            )
                    VALUES  (
                            ---
                            );
            End IF;
    END IF;
 END IF;
END TRIGGER_NAME;

另一种方法是使用显式游标,它在出现错误时不会返回错误。空的:

DECLARE
   CURSOR cur_sample is select dummy from dual where 1=0;
   v_dummy dual.dummy%type;
BEGIN
   IF CONDITION1  THEN
         open cur_sample;
         fetch cur_sample into v_dummy;
         close cur_sample;
         IF CONDITION2 THEN
                -- SELECT COUNT
             IF CONDITION3 THEN
                    INSERT INTO TABLE
                            (
                            --- 
                            )
                    VALUES  (
                            ---
                            );
            End IF;
       END IF;
    END IF;
END;

PL/SQL has no way to return to the site of the error, so you need to create a block around the portion you want to ignore specific errors:

IF CONDITION1  THEN
         BEGIN
         -- SELECT  STATEMENT MIGHT RETURN DATA
         EXCEPTION
             WHEN NO_DATA_FOUND THEN
                 NULL;
         END;
         IF CONDITION2 THEN
                -- SELECT COUNT
             IF CONDITION3 THEN
                    INSERT INTO TABLE
                            (
                            --- 
                            )
                    VALUES  (
                            ---
                            );
            End IF;
    END IF;
 END IF;
END TRIGGER_NAME;

An alternative is to use an explicit cursor, which does not return an error when it is empty:

DECLARE
   CURSOR cur_sample is select dummy from dual where 1=0;
   v_dummy dual.dummy%type;
BEGIN
   IF CONDITION1  THEN
         open cur_sample;
         fetch cur_sample into v_dummy;
         close cur_sample;
         IF CONDITION2 THEN
                -- SELECT COUNT
             IF CONDITION3 THEN
                    INSERT INTO TABLE
                            (
                            --- 
                            )
                    VALUES  (
                            ---
                            );
            End IF;
       END IF;
    END IF;
END;
空宴 2024-12-21 21:44:19

取决于你所说的“正确”是什么意思。是的,您所呈现的内容在语法上是有效的。但您还没有告诉我们您真正想要发生的事情,因此我们无法告诉您您发布的代码是否真正能实现您想要的效果。

从业务逻辑的角度来看,如果您的 SELECT INTO 返回 0 行,您确定这真的不是错误吗?如果您捕获并吞下异常,则意味着您知道这并不是真正的错误。但是,如果您正在编写 SELECT INTO 代码,则意味着您只需要一行。这两种说法当然有可能都是正确的,但更常见的是,它确实是一个例外,并且不应简单地接受和忽视它。

一般来说,我更愿意将异常处理程序尽可能靠近可能抛出异常的查询。我会发现这样更干净

IF condition1
THEN
  BEGIN
    <<select statement>>
  EXCEPTION
    WHEN no_data_found
    THEN
      <<do something>>
  END;

  IF condition2
  THEN
    ...
  END IF;
END IF;

,这样,如果您最终在程序中的多个位置可能抛出 NO_DATA_FOUND 异常,那么就会清楚哪些异常是预期的,哪些异常是意外的。

当您达到三层嵌套 IF 语句的程度时,我倾向于怀疑您想要将代码重构为多个过程以使代码更清晰。例如,与其使用嵌套的 PL/SQL 块来执行 SELECT 语句、捕获异常并处理异常,不如使用一个单独的函数来完成所有这些操作,然后从触发器中调用该函数,这可能会更清楚。

Depends what you mean by "correct". What you have presented is syntactically valid, yes. But you haven't told us what you actually want to happen so we can't tell you whether the code you posted will actually do what you want.

From a business logic standpoint, are you certain that it really is not an error if your SELECT INTO returns 0 rows? If you are catching and swallowing an exception, that means that you know that it's not really an error. If you're coding a SELECT INTO, however, that implies that you expect exactly one row. It's certainly possible that both of these statements are true but it would be more common that it really is an exception and that it shouldn't simply be swallowed and ignored.

In general, I would prefer to put the exception handler as close as possible to the query that might throw the exception as possible. I would find it cleaner to have something like

IF condition1
THEN
  BEGIN
    <<select statement>>
  EXCEPTION
    WHEN no_data_found
    THEN
      <<do something>>
  END;

  IF condition2
  THEN
    ...
  END IF;
END IF;

That way, if you end up with multiple places in your procedure where a NO_DATA_FOUND exception might be thrown, it will be clear which exceptions are expected and which are unexpected.

When you get to the point of having three layers of nested IF statements, I would tend to suspect that you want to refactor the code into multiple procedures to make the code clearer. For example, rather than having a nested PL/SQL block that executes the SELECT statement, catches the exception, and handles the exception, it would probably be clearer to have a separate function that did all that and then call that function from your trigger.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文