Bulk Collect into在使用LIMIT时在集合中存储的行数较少?

时间:2013-08-11 13:54:20

标签: sql collections plsql plsqldeveloper bulk

我编写了以下匿名PL SQL块。

然而,行 dbms_output.put_line(total_tckt_col.LAST)为我输出366(在DBMS_OUTPUT中是SQL Developer),当没有设置限制时这是正确的。

如果100语句中的限制设置为FETCH,那么dbms_output.put_line(total_tckt_col.LAST)会给我66

我在这里做错了什么?

    DECLARE

           CURSOR cur_total_tckt  
            is
                select  t.ticket_id ticket_id, t.created_date created_date, t.created_by created_by, t.ticket_status ticket_status, 
                t.last_changed last_changed, h.created_date closed_date
                    from n01.cc_ticket_info t
                    inner join n01.cc_ticket_status_history h 
                    on (t.ticket_id = h.ticket_id)
                    where t.last_changed >= '6/28/2012 17:28:59' and t.last_changed < (sysdate + interval '1' day);

        type total_tckt_colcn
        is
            TABLE OF cur_total_tckt%rowtype;
            total_tckt_col total_tckt_colcn;
            total_coach_col total_tckt_colcn;
        begin

        total_tckt_col  := total_tckt_colcn ();
        total_coach_col := total_tckt_colcn ();
            OPEN cur_total_tckt;
            loop
                fetch cur_total_tckt bulk collect into total_tckt_col;
 --  fetch cur_total_tckt bulk collect into total_tckt_col limit 100;
            EXIT
            WHEN (cur_total_tckt%NOTFOUND);
            END LOOP ;
            CLOSE cur_total_tckt;   

            dbms_output.put_line(total_tckt_col.LAST);  

            FOR i IN total_tckt_col.first..total_tckt_col.last
            LOOP

            dbms_output.put_line(i);

            END LOOP;
        end;

1 个答案:

答案 0 :(得分:3)

问题是当您将限制设置为100进行循环时,您将删除之前的获取结果。

所以3次获取100行,每次循环时都会被删除,并且在最后一次获取66时,所以你得到66的结果。

您需要积累所有结果以获得正确的计数。

要正确使用带限制的批量收集,请参阅此示例:

PROCEDURE process_all_rows (limit_in IN PLS_INTEGER DEFAULT 100)
IS
    CURSOR employees_cur 
    IS 
        SELECT * FROM employees;

    TYPE employees_aat IS TABLE OF employees_cur%ROWTYPE
        INDEX BY PLS_INTEGER;

    l_employees employees_aat;
BEGIN   
    OPEN employees_cur;
    LOOP
        FETCH employees_cur 
            BULK COLLECT INTO l_employees LIMIT limit_in;

        FOR indx IN 1 .. l_employees.COUNT 
        LOOP
            analyze_compensation (l_employees(indx));
        END LOOP;

        EXIT WHEN l_employees.COUNT < limit_in;

   END LOOP;

   CLOSE employees_cur;
END process_all_rows;

所以你的for循环应该驻留在普通循环中,你可以在其中批量收集。

所以正确的代码是:

DECLARE

           CURSOR cur_total_tckt  
            is
                select  t.ticket_id ticket_id, t.created_date created_date, t.created_by created_by, t.ticket_status ticket_status, 
                t.last_changed last_changed, h.created_date closed_date
                    from n01.cc_ticket_info t
                    inner join n01.cc_ticket_status_history h 
                    on (t.ticket_id = h.ticket_id)
                    where t.last_changed >= '6/28/2012 17:28:59' and t.last_changed < (sysdate + interval '1' day);

        type total_tckt_colcn
        is
            TABLE OF cur_total_tckt%rowtype;
            total_tckt_col total_tckt_colcn;
            total_coach_col total_tckt_colcn;
        begin

        total_tckt_col  := total_tckt_colcn ();
        total_coach_col := total_tckt_colcn ();
            OPEN cur_total_tckt;
            loop

             fetch cur_total_tckt bulk collect into total_tckt_col limit 100;


            dbms_output.put_line(total_tckt_col.LAST);  

            FOR i IN total_tckt_col.first..total_tckt_col.last
            LOOP

            dbms_output.put_line(i);

            END LOOP;

            EXIT
            WHEN (cur_total_tckt%NOTFOUND);
            END LOOP ;
            CLOSE cur_total_tckt;
        end;