2014-02-05 27 views
1

我有一个关于引用游标的问题,并在返回它们的内容之前更新它们包含的行。 具体做法是:更新Oracle中参考光标返回的行

让我们说,我有一个表“人”与以下条目:

 
Id FirstName LastName  Status 
3 John  struth  pending 
4 Mark  roberts  pending 
1 George  jobs  pending 
2 George  Einstein working 

其中id是主键。

,我有一个Oracle PL/SQL过程看起来像这样:

PROCEDURE p_get_2_pending_people(p_result OUT REF CURSOR) 
BEGIN 

OPEN p_result FOR 
SELECT * from PEOPLE p 
WHERE p.Status = 'pending' 
AND rownum <=2; 

END p_get_2_pending_people; 

这将退还给我2个随机排了3可用的。 但是我也想标记这两行同时工作。 我想知道我该怎么做。如果我首先将它们标记为正在工作并且 然后尝试返回它们,则光标不会返回任何内容。如果我第一个 用光标获取它们,然后我写同样的东西来更新 他们我不能保证相同的2行将被带回 (在3个可用的挂起行中)。最后,如果我更新光标的内容 ,那么当我的过程向调用者返回 结果时,光标将为空。

感谢

编辑:我添加了表

+0

是否有该表的唯一键? –

+0

是的,只是在例子 –

回答

1

本例首先确实更新了主键,事后返回受影响的行。如果您在过程中没有COMMIT,那么行当然会被锁定。

CARDINALITY -hint应该产生更好的执行计划,避免全表扫描。

CREATE OR REPLACE TYPE t_ids AS TABLE OF NUMBER(12); 

PROCEDURE p_get_2_pending_people(p_result OUT SYS_REFCURSOR) AS 
    ids  t_ids; 
BEGIN 
    UPDATE people 
    SET status = 'pending' 
    WHERE ROWNUM <= 2 
    RETURNING id 
    BULK COLLECT INTO ids; 

    OPEN p_result FOR 
    SELECT * 
    FROM PEOPLE p 
    WHERE p.id IN (SELECT /*+ CARDINALITY(t 2) */ COLUMN_VALUE FROM TABLE(ids) t); 
END p_get_2_pending_people; 
+0

' WHERE p.id IN(SELECT/* + CARDINALITY(t 2)*/COLUMN_VALUE FROM TABLE(ids))'中添加了'',你可以写成WHERE p.id MEMBER OF ids' –

+0

精彩的解决方案谢谢。我会稍微尝试一下为了完整起见,如果没有主键,您会有什么建议? –

+0

@ Wernfried:没错,但是如何避免使用此解决方案的全表扫描?我的解决方案需要0.5ms和500.000条记录,而您的解决方案需要300ms。有我能提供的另一个提示吗? –