получение целых данных в коллекции с помощью oracle PLSQL Bulk collect с предложением limit - PullRequest
0 голосов
/ 06 октября 2018

У меня есть одна таблица с именем 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 голосов
/ 06 октября 2018

Приведенная ниже логика не дает требуемого результата

Дикая догадка: вы получаете только двенадцать строк.Это знакомая ошибка с предложением LIMIT.Эта строка является проблемой:

EXIT WHEN c_get_employee%NOTFOUND; 

У вас есть 14 записей в EMP: ограничение 3 означает, что вы собираете четыре набора записей.Последний FETCH собирает только 2 записи.PL / SQL интерпретирует это как NOTFOUND.Решение состоит в том, чтобы проверить размер коллекции:

EXIT WHEN l_employee.count() = 0; 

Я хочу загрузить все данные в коллекцию и закрыть курсор. После этого я хочу открыть коллекцию и использовать данные длябизнес-логика

Это не то, как работает BULK COLLECT ... LIMIT.Смысл предложения LIMIT заключается в том, чтобы ограничить количество записей, извлекаемых за один раз.Это необходимо делать, когда запрашиваемые данные слишком велики для обработки за один раз.Коллекции PL / SQL - это структуры памяти, которые хранятся в распределении памяти сеанса: если они становятся слишком большими, они взрывают PGA.(Определение «слишком большой» будет зависеть от того, как ваш администратор БД настроил PGA.)

Итак, если у вас небольшой набор результатов, отбросьте предложение LIMIT и заполните коллекцию за одну выборку.Но если у вас достаточно данных, чтобы потребовать предложение LIMIT, вам нужно включить цикл бизнес-логики в цикл выборки.

0 голосов
/ 06 октября 2018

Вы выходите из цикла слишком рано.Вам нужно остановить цикл выборки после цикла for и закрыть курсор после этого.

Также, как указывало @APC, условие выхода должно использовать счетчик выбранных результатов вместо NOTFOUND на курсоре.В противном случае, если последняя выборка имеет меньше записей, чем размер выборки, NOTFOUND будет истинным и цикл завершится неправильно.

Попробуйте это:

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; 
...