使用oracle PLSQL将整个数据放入集合中带限制子句的批量收集

时间:2018-10-06 12:15:12

标签: oracle plsql bulk-operations

我有一张名为EMP的表,具有140000行,我需要将整个数据保存到集合中。如何使用“ BULK COLLECT ..LIMIT”子句功能扩展集合并将整个数据加载到集合中。

以下逻辑未提供所需结果,因为数据已被新记录覆盖。请向我提出逻辑。

DECLARE 
    CURSOR c_get_employee IS 
      SELECT empno, 
             ename, 
             deptno, 
             sal 
      FROM   emp; 
    TYPE t_employee 
      IS TABLE OF c_get_employee%ROWTYPE INDEX BY inary_integer; 
    l_employee T_EMPLOYEE; 
BEGIN 
    OPEN c_get_employee; 

    LOOP 
        FETCH c_get_employee bulk collect INTO l_employee limit 300; 

        EXIT WHEN l_employee.count = 0; 
    END LOOP; 

    CLOSE c_get_employee; 

    FOR i IN 1..l_employee.count LOOP 
        dbms_output.Put_line (L_employee(i).ename 
                              ||'<-->' 
                              ||L_employee(i).sal); 
    END LOOP; 
EXCEPTION 
    WHEN OTHERS THEN 
      dbms_output.Put_line ('Unexpected error :- ' 
                            || SQLERRM); 
END; 

2 个答案:

答案 0 :(得分:1)

您退出循环太早了。您需要在for循环之后停止fetch循环,然后在其之后关闭光标。

此外,正如@APC指出的那样,退出条件应使用获取的结果计数代替光标上的NOTFOUND。否则,如果最后一次获取的记录少于获取的大小,则NOTFOUND将为true,并且循环将错误终止。

尝试一下:

DECLARE 
    CURSOR c_get_employee IS 
      SELECT empno, 
             ename, 
             deptno, 
             sal 
      FROM   emp; 
    TYPE t_employee 
      IS TABLE OF c_get_employee%ROWTYPE INDEX BY binary_integer; 
    l_employee T_EMPLOYEE; 
BEGIN 
    OPEN c_get_employee; 

    LOOP 
        FETCH c_get_employee bulk collect INTO l_employee limit 3; 
        EXIT WHEN l_employee.count = 0;

        FOR i IN 1..l_employee.count LOOP 
            dbms_output.Put_line (L_employee(i).ename 
                                  ||'<-->' 
                                  ||L_employee(i).sal); 
        END LOOP;
    END LOOP; 
    CLOSE c_get_employee; 
EXCEPTION 
    WHEN OTHERS THEN 
      dbms_output.Put_line ('Unexpected error :- ' 
                            || SQLERRM); 
END; 

答案 1 :(得分:1)

  

以下逻辑未给出所需结果

疯狂的猜测:您只会得到十二行。这是一个熟悉的LIMIT子句。这是问题所在:

EXIT WHEN c_get_employee%NOTFOUND; 

您在EMP中有14条记录:限制为3表示您收集了四组记录。最后一个FETCH仅收集2条记录。 PL / SQL将此解释为NOTFOUND。解决方案是检查集合的大小:

EXIT WHEN l_employee.count() = 0; 

  

我想将整个数据加载到集合中并关闭游标。之后,我想打开集合并将数据用于业务逻辑

那不是BULK COLLECT ... LIMIT的工作原理。 LIMIT子句的意义是 limit 一次获取的记录数。当查询的数据太大而无法在单个提取中处理时,我们需要执行此操作。 PL / SQL集合是保存在会话的内存分配中的内存结构:如果它们太大,则会破坏PGA。 (“太大”的定义取决于您的DBA如何配置PGA。)

因此,如果结果集较小,则放弃LIMIT子句,并通过一次提取填充集合。但是,如果您有足够的数据来要求LIMIT子句,则需要在fetch循环中包括业务逻辑循环。