我有一个数据库表,我或多或少像队列一样对待。我正在尝试从中获取单个项目。这是有效的,除非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;
答案 0 :(得分: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;
请注意,此代码不会阻止两个不同的调用者在同一行上工作。如果两个会话同时调用此过程,则两者都完全可能选择同一行。如果您想阻止这种情况,SELECT
需要使用FOR UPDATE
子句锁定它所选择的行。
答案 1 :(得分:4)
在这种情况下,您无能为力:
exception
when no_data_found then
null;
end;
这会在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;
答案 2 :(得分:2)
如何避免异常处理:
/* returns X */
SELECT DUMMY FROM DUAL WHERE 1 = 1;
/* no data found */
SELECT DUMMY FROM DUAL WHERE 1 = 0;
/* returns NULL */
SELECT MIN(DUMMY) FROM DUAL WHERE 1 = 0;
答案 3 :(得分:1)
select null from ssq_emails
仍将获得1403。我不确定你想在异常处理程序中做任何事情;不确定你的来电者如何处理pRecs
为空。
答案 4 :(得分:1)
通过这样做解决了这个问题:
EXCEPTION
WHEN no_data_found THEN
OPEN pRecs FOR
SELECT NULL
FROM SSQ_EMAILS s
WHERE s.id IS NULL;
它的工作原因是必须打开RefCursor。我需要一个空的结果,这似乎是一种安全的方法来保证,因为ID是PK而不能为null。