PL/SQL 找不到数据异常处理

Posted

技术标签:

【中文标题】PL/SQL 找不到数据异常处理【英文标题】:PL/SQL no data found exception handling 【发布时间】:2017-02-14 11:02:07 【问题描述】:

我有一个 EMAILS 表,其中包含以下列:ROUTINE、EMAILS 和 COPIES,它们定义了应该使用 UTL_MAIL 将特定过程的结果发送给谁(至/cc)。

我有以下代码:

PROCEDURE myproc AS
  NO_EMAIL_FOUND EXCEPTION;
  e EMAILS%ROWTYPE;
  x NUMBER;
BEGIN

  --fetch data
  SELECT x INTO x FROM <...>;

  --fetch emails
  SELECT * INTO e FROM emails WHERE routine='FRS_WEEKLY';
  IF e.emails IS NULL AND e.copies IS NULL THEN
    RAISE NO_EMAIL_FOUND;
  END IF;

  <send mail code using UTL_MAIL>;

  EXCEPTION
    WHEN NO_EMAIL_FOUND THEN <code1>;
    WHEN NO_DATA_FOUND THEN <code2>;
    WHEN OTHERS THEN NULL; --RAISE;

END myproc;

我希望 myproc 在 EMAILS 表中没有电子邮件时执行 code1。我的问题是没有引发 NO_EMAIL_FOUND 异常并且 code2 执行,因为在 SELECT 语句中引发了 NO_DATA_FOUND 异常。如何避免这种情况?

【问题讨论】:

【参考方案1】:

试试这个:

PROCEDURE myproc AS
    NO_EMAIL_FOUND EXCEPTION;
    e EMAILS%ROWTYPE;
    x NUMBER;
BEGIN

    BEGIN
        --fetch data
        SELECT x INTO x FROM <...>;

        --fetch emails
        BEGIN
            SELECT * INTO e FROM emails WHERE routine='FRS_WEEKLY';
        EXCEPTION WHEN NO_DATA_FOUND THEN
            RAISE NO_EMAIL_FOUND;
        END;
        IF e.emails IS NULL AND e.copies IS NULL THEN
            RAISE NO_EMAIL_FOUND;
        END IF;

        <send mail code using UTL_MAIL>;

    EXCEPTION
        WHEN NO_EMAIL_FOUND THEN <code1>;
        WHEN NO_DATA_FOUND THEN <code2>;
        WHEN OTHERS THEN NULL; --RAISE;
    END;

END myproc;

【讨论】:

是的,解决方案是将我的 SELECT 封装到内部 BEGIN EXCEPTION END 结构中,在内部捕获 NO_DATA_FOUND,并根据需要将其传播到 NO_EMAIL_FOUND,最后捕获它。 IF e.emails IS NULL ... 则不再需要。谢谢。【参考方案2】:

使用这个:

PROCEDURE myproc AS
  NO_EMAIL_FOUND EXCEPTION;
  e EMAILS%ROWTYPE;
  x NUMBER;
BEGIN

  --fetch data
  SELECT x INTO x FROM <...>;

  --fetch emails
  BEGIN
    SELECT * INTO e FROM emails WHERE routine='FRS_WEEKLY';
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      RAISE NO_EMAIL_FOUND;
  END;

  IF e.emails IS NULL AND e.copies IS NULL THEN
    RAISE NO_EMAIL_FOUND;
  END IF;

  <send mail code using UTL_MAIL>;

  EXCEPTION
    WHEN NO_EMAIL_FOUND THEN <code1>;
    WHEN NO_DATA_FOUND THEN <code2>;
    WHEN OTHERS THEN NULL; --RAISE;

END myproc;

我希望您知道此例程只能处理一封电子邮件;如果有多个,则会引发 TOO_MANY_ROWS 异常。

【讨论】:

列 'routine' 是我的 EMAILS 表中的 PK,因此不会有 TOO_MANY_ROWS(每个过程执行一条记录和一封邮件)。当然,一封电子邮件,但有更多的电子邮件地址。

以上是关于PL/SQL 找不到数据异常处理的主要内容,如果未能解决你的问题,请参考以下文章

PL/SQL数据开发那点事

PL/SQL 异常错误处理

PL/SQL 引发处理异常

动态 SQL/异常处理 -00942 - Oracle PL/SQL [重复]

PL\SQL 函数之间的异常处理

PL/SQL 异常处理