使用oracle PLSQL Bulk COLLET with limit子句将整个数据放入集合

使用oracle PLSQL Bulk COLLET with limit子句将整个数据放入集合,oracle,plsql,bulk-operations,Oracle,Plsql,Bulk Operations,我有一个名为EMP的表,有140000行,我需要将整个数据保存到集合中。如何使用“BULK COLLECT..LIMIT”子句功能扩展集合并将整个数据加载到集合中 以下逻辑未提供所需结果,因为数据已被新记录覆盖。请向我建议逻辑 DECLARE CURSOR c_get_employee IS SELECT empno, ename, deptno, sal FROM em

我有一个名为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; 
声明
光标c_get_employee为
选择empno,
艾娜,
德普诺,
萨尔
来自emp;
类型t_雇员
是c_get_employee%行类型索引的表,由一个二元整数表示;
l_员工T_员工;
开始
打开c_get_employee;
环
取c_get_employee bulk collect至l_employee limit 300;
l_employee.count=0时退出;
端环;
关闭c_get_员工;
对于1..l_employee.count循环中的i
dbms_output.Put_line(L_employee(i).ename
||'' 
||L_员工(i.sal);
端环;
例外情况
当其他人
dbms_output.Put_行('意外错误:-'
||SQLERRM);
结束;

您过早退出循环。您需要在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; 
声明
光标c_get_employee为
选择empno,
艾娜,
德普诺,
萨尔
来自emp;
类型t_雇员
是c_get_employee%行类型索引的表,由二进制_整数表示;
l_员工T_员工;
开始
打开c_get_employee;
环
取c_get_employee bulk collect到l_employee limit 3中;
l_employee.count=0时退出;
对于1..l_employee.count循环中的i
dbms_output.Put_line(L_employee(i).ename
||'' 
||L_员工(i.sal);
端环;
端环;
关闭c_get_员工;
例外情况
当其他人
dbms_output.Put_行('意外错误:-'
||SQLERRM);
结束;
以下逻辑未给出所需结果

胡猜:你只得到12排。这是一个熟悉的限制条款。这条线就是问题所在:

EXIT WHEN c_get_employee%NOTFOUND; 
您在EMP中有14条记录:限制为3意味着您收集了四组记录。最后一次获取仅收集2条记录。PL/SQL将其解释为
NOTFOUND
。解决方案是检查集合的大小:

EXIT WHEN l_employee.count() = 0; 

我希望将整个数据加载到集合中并关闭光标,然后打开集合并将数据用于业务逻辑

这不是批量收集的方式。。。限制工作。LIMIT子句的目的是,呃,限制一次获取的记录数量。当查询的数据太大而无法在一次获取中处理时,我们需要这样做。PL/SQL集合是会话内存分配中保存的内存结构:如果它们太大,将破坏PGA。(定义“太大”将取决于DBA如何配置PGA。)


因此,如果您有一个小的结果集,请放弃LIMIT子句,在一次获取中填充集合。但是,如果您有足够的数据需要LIMIT子句,则需要在fetch循环中包含业务逻辑循环。

嗨,Gurvinder Singh,我的要求是,首先,我希望将游标中的整个数据保存到集合中。然后,我希望关闭游标并打开集合,并希望使用集合中的此数据创建业务逻辑。大容量集合将在下一次获取中替换变量中的数据。除此之外,你不应该阅读集合中的整张表格。如果记录的数量很小,可能会增加获取大小以匹配记录的数量。我同意您的观点(大容量收集将在下一次获取中替换变量中的数据),但我希望使用“大容量收集…限制”从游标加载整个数据“将功能加载到集合中。@MastanSky,那么您想加载所有行,但也要限制它们吗?”?不清楚当您不想限制任何内容时,为什么会有
limit
子句。“下面的逻辑没有给出所需的结果”。如果您定义预期输出并解释实际输出的差异,而不是让我们猜测问题所在,那么每个人的生活通常都会更轻松。亲爱的团队,我想将整个数据加载到集合中并关闭光标。然后,我想打开集合并将数据用于业务逻辑。