-1

我有一张名为 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; 
4

2 回答 2

1

您过早退出循环。您需要在 for 循环之后停止 fetch 循环并在此之后关闭光标。

此外,正如@APC 指出的那样,退出条件应该使用获取结果的计数而不是NOTFOUND游标。否则,如果最后一次 fetch 的记录少于 fetch 大小,则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; 
于 2018-10-06T12:21:46.590 回答
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 子句的要点是,呃,限制一次获取的记录数。当查询的数据太大而无法在一次提取中处理时,我们需要这样做。PL/SQL 集合是保存在会话内存分配中的内存结构:如果它们变得太大,就会破坏 PGA。(“太大”的定义取决于您的 DBA 如何配置 PGA。)

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

于 2018-10-06T12:24:22.183 回答