处理此Oracle ORA-01403的正确方法是什么:没有找到数据异常?

Chr*_*mes 9 oracle stored-procedures exception

我有一个数据库表,我或多或少像一个队列.我正在尝试从中获取单个项目.这是有效的,除非SELECT..INTO失败(如果队列中只有一个项目,并且不同机器上的两个用户尝试并获取它,则可能会发生这种情况;只有一个将获胜).

这导致了熟悉的ORA-01403:没有找到数据异常.我试图更改SP,以便它在这种情况下返回NULL记录 - 同样的结果你得到它一个查询无法找到任何记录 - 但无济于事.我在这里做错了.

PROCEDURE sp_GetNextEmailFromQueue (pAgentId IN NUMBER, pRecs OUT recordSet)
  IS
  EMAIL_ID INTEGER;
  BEGIN

     SELECT id INTO EMAIL_ID FROM
           (SELECT id, is_replied_to, is_being_worked, date_received 
           FROM SSQ_EMAILS
           WHERE is_replied_to = 0 AND is_being_worked =0
           ORDER BY date_received ASC)
     WHERE rownum = 1;


    UPDATE SSQ_EMAILS x 
             SET x.is_being_worked = 1,
                 x.agent_id = pAgentId,
                 x.work_started_date = SYSDATE
             WHERE x.id = EMAIL_ID;

    OPEN pRecs FOR
      SELECT x.id,
             x.message_id,
             x.to_email,
             x.from_email,
             x.subject,
             x.message,
             x.date_received,
             x.href_link,
             x.is_being_worked,
             x.work_started_date,
             x.is_replied_to
        FROM SSQ_EMAILS x
        WHERE x.id = EMAIL_ID;

        EXCEPTION
          WHEN no_data_found 
            THEN 
              OPEN pRecs FOR
              SELECT NULL
              FROM SSQ_EMAILS;

  END;
Run Code Online (Sandbox Code Playgroud)

Jus*_*ave 7

我将异常处理程序放在实际导致错误抛出的代码片段周围.如果email_id为NULL,UPDATE则不会更新任何行,并且SELECT不会返回任何行.

PROCEDURE sp_GetNextEmailFromQueue (pAgentId IN NUMBER, pRecs OUT recordSet)
  IS
  EMAIL_ID INTEGER;
  BEGIN
    BEGIN
      SELECT id 
        INTO EMAIL_ID 
        FROM (SELECT id, is_replied_to, is_being_worked, date_received 
                FROM SSQ_EMAILS
               WHERE is_replied_to = 0 AND is_being_worked =0
               ORDER BY date_received ASC)
       WHERE rownum = 1;
    EXCEPTION
      WHEN no_data_found 
      THEN
        email_id := null;
    END;

    UPDATE SSQ_EMAILS x 
             SET x.is_being_worked = 1,
                 x.agent_id = pAgentId,
                 x.work_started_date = SYSDATE
             WHERE x.id = EMAIL_ID;

    OPEN pRecs FOR
      SELECT x.id,
             x.message_id,
             x.to_email,
             x.from_email,
             x.subject,
             x.message,
             x.date_received,
             x.href_link,
             x.is_being_worked,
             x.work_started_date,
             x.is_replied_to
        FROM SSQ_EMAILS x
        WHERE x.id = EMAIL_ID;
  END;
Run Code Online (Sandbox Code Playgroud)

但请注意,此代码不会阻止两个不同的调用者在同一行上工作.如果两个会话同时调用此过程,则两者都完全可能选择同一行.如果要防止这种情况,则SELECT需要使用FOR UPDATE子句锁定它所选择的行.


小智 4

在这种情况下你什么也做不了:

exception
  when no_data_found then
    null;
end;
Run Code Online (Sandbox Code Playgroud)

这会返回 null 对pRecs吧?

编辑

第二种方法:

cursor c_mail is
  SELECT id  
    FROM
       (SELECT id, is_replied_to, is_being_worked, date_received 
          FROM SSQ_EMAILS
         WHERE is_replied_to = 0 AND is_being_worked =0
         ORDER BY date_received ASC)
   WHERE rownum = 1;
....
open c_mail;
fetch c_mail into email_id; -- no_data_found not happens
close c_mail;
Run Code Online (Sandbox Code Playgroud)