我有一张名为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;
答案 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循环中包括业务逻辑循环。