BULK收集多个系列

时间:2017-10-11 17:10:28

标签: sql oracle plsql cursor oracle12c

我想知道使用BULK COLLECT INTO多个集合是否保证行中相应的列在嵌套表中具有相同的索引。

示例:

CREATE TABLE tx AS
SELECT CAST(level AS INT) AS col1, level || 'a' AS col2, level || 'b' as col3
FROM dual
CONNECT BY level <= 100000;

数据:

col1    col2   col3
1       1a     1b
2       2a     2b
3       3a     3b
4       4a     4b
5       5a     5b
...     ...    ...

代码:

DECLARE
   CURSOR cur IS SELECT /*+parallel(4)*/col1, col2, col3 FROM tx;

   TYPE t1 IS TABLE of INT;
   TYPE t2 IS TABLE of VARCHAR2(20);

   vt1 t1;
   vt2 t2;
   vt3 t2;
BEGIN
   OPEN cur;
   FETCH cur BULK COLLECT INTO vt1, vt2, vt3 LIMIT 1000;

   LOOP
      FOR i IN 1..vt1.COUNT LOOP
         DBMS_OUTPUT.put_line('i => '|| i || ' vt1 => ' || vt1(i) 
                              || ' vt2 => '|| vt2(i) || ' vt3 =>' || vt3(i));
      END LOOP;

      EXIT WHEN cur%NOTFOUND;
      FETCH cur BULK COLLECT INTO vt1, vt2, vt3 LIMIT 1000;    
   END LOOP;   
   CLOSE cur;
END;

输出:

i => 1 vt1 => 22418 vt2 => 22418a vt3 =>22418b
i => 2 vt1 => 22419 vt2 => 22419a vt3 =>22419b
i => 3 vt1 => 22420 vt2 => 22420a vt3 =>22420b
i => 4 vt1 => 22421 vt2 => 22421a vt3 =>22421b
i => 5 vt1 => 22422 vt2 => 22422a vt3 =>22422b
i => 6 vt1 => 22423 vt2 => 22423a vt3 =>22423b

所以在每一行中总是有相同的前缀。或者在某些情况下可能会得到类似的东西:

i => 1 vt1=> 100 vt2=>200a vt3=>300b

备注:我知道我可以定义记录类型并只使用一个集合。

寻找官方消息来源的答案。

3 个答案:

答案 0 :(得分:3)

Oracle的PL / SQL语言参考文档没有明确说明来自同一行的值将具有相同的索引,但确实说:

  

PL / SQL处理BULK COLLECT子句,类似于在LOOP语句中处理FETCH语句的方式。

此外,关于BULK COLLECT的章节给出的示例隐含地假设来自同一行的值将具有相同的索引。例如。这来自 Oracle PL / SQL语言参考中的示例12-22 for 12.1。

FOR i IN names.FIRST .. names.LAST
LOOP
  DBMS_OUTPUT.PUT_LINE('  Employee ' || names(i) || ': $' || sals(i));
END LOOP;

请参阅:https://docs.oracle.com/database/121/LNPLS/tuning.htm#GUID-541A8B35-9B8F-432F-9E30-E73305A6E17C__BABCCJCB

答案 1 :(得分:1)

抱歉,我没有任何官方消息来源,但我猜这种去同步是不可能的,因为这意味着如果你使用了记录类型,那么你的集合中最终会有一个损坏的记录。

ex:rec.vt1 => 100 rec.vt2 => 200a rec.vt3 => 300a

这基本上意味着BULK COLLECT不可靠。

答案 2 :(得分:1)

除了Matthew McPeak发现的内容之外,我认为这里的关键实际上是FETCH statement,它总是从表中选择整行(或行):

  

FETCH语句从a的结果集中检索数据行   多行查询 - 一次一行,一次几行或全部   一次排 - 并将数据存储在变量,记录或   集合。

因此,在获取行之后,Oracle可以将它们放入记录或一个或多个集合(如您的示例),但无论哪种方式,索引都是一致的(从同一行拉出)。