使用 LOOP 将 Oracle 批量收集到集合中

Posted

技术标签:

【中文标题】使用 LOOP 将 Oracle 批量收集到集合中【英文标题】:Oracle Bulk Collect into Collection using LOOP 【发布时间】:2017-08-21 12:58:16 【问题描述】:

http://www.oracle.com/technetwork/issue-archive/2008/08-mar/o28plsql-095155.html

在此页面中,他们提到:

当您使用 BULK COLLECT 和集合从游标中获取数据时,切勿依赖游标属性来决定是否终止循环和数据处理。

他提到,为了确保我们的查询处理所有行,我们应该

不使用:

何时退出

光标%NOTFOUND;

我们应该使用:

何时退出

collectionvariable.count=0;

是什么原因?

【问题讨论】:

原因在文章中给出,如果你读到最后。 在您参考的文章中有说明。请参阅Code Listing 2 及其解释。 有table_with_227_rows_cur的例子 【参考方案1】:

文章明确指出,当使用cur%NOTFOUND 时,它会跳过处理一些记录。

请检查独立示例:

DECLARE
  TYPE item_tab IS TABLE OF PLS_INTEGER;
  l_item item_tab;
  CURSOR get_item_value IS
  SELECT LEVEL
  FROM dual
  CONNECT BY LEVEL <= 25;
BEGIN
  OPEN get_item_value;
  LOOP
     FETCH get_item_value BULK COLLECT INTO l_item LIMIT 10;  -- 10    10    5
     EXIT WHEN get_item_value%NOTFOUND;                       -- FALSE FALSE TRUE
     DBMS_OUTPUT.put_line(l_item.COUNT);       
  END LOOP;
  CLOSE get_item_value;
END;

输出:

10
10
-- 5 record left

第二个版本:

DECLARE
  TYPE item_tab IS TABLE OF PLS_INTEGER;
  l_item item_tab;
  CURSOR get_item_value IS
  SELECT LEVEL
  FROM dual
  CONNECT BY LEVEL <= 25;
BEGIN
  OPEN get_item_value;
  LOOP
     FETCH get_item_value BULK COLLECT INTO l_item LIMIT 10;   -- 10   10   5   0
     EXIT WHEN l_item.COUNT = 0;                               -- F    F    F   T
     DBMS_OUTPUT.put_line(l_item.COUNT);
  END LOOP;
  CLOSE get_item_value;
END;

输出:

10
10
5

【讨论】:

谢谢。我确实看到它被提及为“可能跳过处理某些记录”。我想知道它如何跳过记录,您的示例清楚地解释了它。但它是如何始终跳过这一点的呢?

以上是关于使用 LOOP 将 Oracle 批量收集到集合中的主要内容,如果未能解决你的问题,请参考以下文章

从 Oracle 游标批量收集列的子集

一个批量收集操作循环中的两个(或多个)DML

Oracle - 使用 CURSOR LOOP 进行批量更新

plsql-Oracle 集合

Oracle/PLSQL 在 BULK COLLECT 之后处理 for LOOP 中的所有数据

Oracle:批量收集性能