在 Oracle 中更新引用游标返回的行

Posted

技术标签:

【中文标题】在 Oracle 中更新引用游标返回的行【英文标题】:Updating the rows returned by a reference cursor in Oracle 【发布时间】:2014-02-05 11:35:33 【问题描述】:

我有一个关于引用游标和在返回其内容之前更新它们包含的行的问题。 具体来说:

假设我有一个“人”表,其中包含以下条目:

Id 名字 姓氏 状态 3 John struth 待定 4 马克罗伯特待定 1 乔治职位待定 2 乔治·爱因斯坦工作

其中 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;

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

谢谢

编辑:我为表添加了主键

【问题讨论】:

该表是否有唯一键? 是的,只是在示例中添加了这一点 【参考方案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;

【讨论】:

WHERE p.id IN ( SELECT /*+ CARDINALITY(t 2) */ COLUMN_VALUE FROM TABLE(ids) ) 你可以写成更短的WHERE p.id MEMBER OF ids 很好的解决方案,谢谢。我会尝试一下为了完整起见,如果没有主键,您会建议什么? @Wernfried:没错,但是您将如何避免使用此解决方案进行全表扫描呢?我的解决方案需要 0.5 毫秒,记录 500.000 条记录,而您的解决方案需要 300 毫秒。我还能提供其他提示吗? @sakiskaliakoudas 如果表中没有主键,您可以返回 rowid 伪列而不是 id。此外,此变体消除了全表扫描。 @sakiskaliakoudas:修正了我的答案,别名 t 丢失了。您不能在提示中使用变量,但数字不需要准确。如果您不提供提示,优化器预计集合的大小是您的块大小(通常为 4096 或 8192)。见asktom.oracle.com/pls/asktom/…

以上是关于在 Oracle 中更新引用游标返回的行的主要内容,如果未能解决你的问题,请参考以下文章

从存储的函数返回更新的行

将多个引用游标从 Oracle 过程返回到 Java

如何调用返回引用游标的Oracle存储过程

MS SQL语句declare游标的求助

SQL记录-PLSQL游标

如何从函数游标返回行并在oracle中循环