Oracle PL/SQL, как вывести, сколько вставок было сделано в операторе FORALL

Каков наилучший способ получить и вывести, сколько строк было вставлено в инструкцию FORALL, приведенную ниже. Я видел SQL%BULK_ROWCOUNT, но я не уверен, как это будет работать в инструкции ниже.

is it

DBMS_OUTPUT.('rows inserted '||SQL%BULK_ROWCOUNT||'');

Нужно ли вышеперечисленное идти в другом операторе FORALL? Для приведенного ниже кода, как мне этого добиться?

DECLARE
  TYPE t_arc_act_plus_trigger1 IS TABLE OF arc_act_plus_triggers1%ROWTYPE;
  v_arc_act_plus_triggers1 t_arc_act_plus_trigger1;

  CURSOR c_arc_act_plus_triggers1 IS
      SELECT /*+ PARALLEL */ apt.*
        FROM act_plus_triggers1 apt
       WHERE NOT EXISTS
                (SELECT 1
                   FROM act_plus_triggers_copy1 aptc
                  WHERE aptc.surr_id = apt.surr_id)
         AND apt.status IN ('EXT', 'EXP');
BEGIN

    OPEN c_arc_act_plus_triggers1;
    LOOP
        FETCH c_arc_act_plus_triggers1 BULK COLLECT INTO v_arc_act_plus_triggers1 LIMIT 10000;  -- limit to 10k to avoid out of memory

        FORALL i IN 1..v_arc_act_plus_triggers1.COUNT
        INSERT /*+ APPEND_VALUES */ INTO arc_act_plus_triggers1 values v_arc_act_plus_triggers1(i);  


        Com0932.get_parameter ('ACT_ARCHIVE_TRIGGER_STOP_YN',l_STOP_PROGRAM_YN);         
        IF l_STOP_PROGRAM_YN = 'Y' THEN
            p_location('insert_into_arc_act_plus - STOP_PROGRAM_YN flag = '||l_STOP_PROGRAM_YN||' so ROLLBACK'); 
            ROLLBACK;
            EXIT;
        END IF; 

        -- **************************************************
        -- Output how many records have been inserted here???
        -- **************************************************

        -- commit after every 10000 records into arc_act_plus_triggers1   
        COMMIT;     
        EXIT WHEN c_arc_act_plus_triggers1%NOTFOUND;


    END LOOP;
    CLOSE c_arc_act_plus_triggers1;

END;

person Shaun Kinnair    schedule 08.02.2017    source источник
comment
Вы пробовали SQL%ROWCOUNT? docs.oracle.com/database/121/LNPLS/static.htm# LNPLS99956   -  person a_horse_with_no_name    schedule 08.02.2017
comment
Предположительно, это будет v_arc_act_plus_triggers1.COUNT? Предполагая, что исключений не происходит, и т.д.   -  person Boneist    schedule 08.02.2017
comment
Никаких исключений не происходит, так как это просто прямая копия из одной таблицы в архивную таблицу, которая является копией.   -  person Shaun Kinnair    schedule 08.02.2017
comment
не уверены, что SQL%ROWCOUNT работает в операторе FORALL? или это @a_horse_with_no_name   -  person Shaun Kinnair    schedule 08.02.2017
comment
Из любопытства, почему бы вам просто не сделать это простым оператором insert into ... select ...? Это будет более эффективно, чем массовый сбор. На самом деле, если подумать, возможно, здесь лучше всего подойдет оператор MERGE.   -  person Boneist    schedule 08.02.2017
comment
Привет @Boneist, я понимаю, что вставка .... select будет быстрее, но они сказали мне, что у них были проблемы с памятью / процессором и продолжительностью прямой вставки, иногда она вставляет 65 000 000 строк, и они хотят способ остановить программу, если она работает слишком долго утром, они могут затем перезапустить задание на следующий день. Я добавил флаг остановки для отображения в коде, чтобы показать, что я имею в виду   -  person Shaun Kinnair    schedule 08.02.2017
comment
Я бы по-прежнему делал это как вставку (или слияние) и просто ограничивал количество строк, вставляемых за цикл. Например. что-то вроде: loop insert into ... select .... where rownum <=10000 and not exists (select ...) ....; exit when sql%rowcount = 0; end loop;   -  person Boneist    schedule 08.02.2017
comment
И, возможно, вам было бы полезно увеличить количество строк, вставляемых за один раз (миллион строк не должен быть слишком напряженным за раз). Если ваша ночная работа занимает несколько часов и возникают проблемы с памятью/процессором, то, что кажется простым оператором вставки, возможно, вам следует сначала посмотреть на настройку вставки. Например. есть соответствующие индексы? Выиграет ли он от превращения в оператор слияния (и, следовательно, от потери несуществующего)? И параллель скорее мешает, чем помогает?   -  person Boneist    schedule 08.02.2017
comment
@ShaunKinnair. Следуя комментариям Бониста, я согласен. 65M строк не должны быть проблемой на разумном сервере/хранилище. Вы можете использовать прямую вставку пути (используя подсказку APPEND) вместе с параллелизмом.   -  person BobC    schedule 08.02.2017


Ответы (1)


Я не проверял, так как мне не с чем тестировать, поэтому, пожалуйста, простите любые «отсутствующие ошибки с точкой с запятой», и я боюсь, что я не в состоянии проверить это на производительность.

Ваш код, кажется, выбирает, какие строки вставлять в таблицу архива на основе их отсутствия в архиве. Поэтому просто используйте INSERT на основе SELECT, ограниченного подходящим значением ROWNUM. Как только вы зафиксируете, в следующий раз в цикле он не будет пытаться получить уже заархивированные строки, поскольку вы только что их зафиксировали.

Я думаю, что это должно быть так же быстро, если не быстрее, чем увеличение объема вставок, с тем преимуществом, что это проще - бритва Оккама и все такое.

DECLARE
  l_commit_count NUMBER := 10000;
  l_rows_copied NUMBER := 0;
BEGIN
    DBMS_OUTPUT.PUT_LINE('Started at '||TO_DATE(SYSDATE, 'DD_MON_YYY HH24:MI:SS');
    LOOP
        INSERT /*+APPEND */
        INTO c_arc_act_plus_triggers1
        SELECT /*+ PARALLEL */ apt.*
            FROM act_plus_triggers1 apt
           WHERE NOT EXISTS
                    (SELECT 1
                       FROM act_plus_triggers_copy1 aptc
                      WHERE aptc.surr_id = apt.surr_id)
             AND apt.status IN ('EXT', 'EXP')
             AND rownum < l_commit_count;

        COMMIT;         
        l_rows := l_rows + SQL%ROWCOUNT;
        EXIT WHEN SQL%ROWCOUNT < 1;
    END LOOP        
    DBMS_OUTPUT.PUT_LINE('Finished at '||TO_DATE(SYSDATE, 'DD_MON_YYY HH24:MI:SS');
    DBMS_OUTPUT.PUT_LINE(TO_CHAR(l_rows)||' rows copied to the archive table');
END;
person BriteSponge    schedule 08.02.2017
comment
Я попробую вышеперечисленное и вернусь к вам - person Shaun Kinnair; 08.02.2017