Oracle PL/SQL 如何输出在 FORALL 语句中进行了多少次插入

Posted

技术标签:

【中文标题】Oracle PL/SQL 如何输出在 FORALL 语句中进行了多少次插入【英文标题】:Oracle PL/SQL how do you output how many inserts have been made in a FORALL statement 【发布时间】:2017-02-08 14:42:02 【问题描述】:

获取和输出在下面的 FORALL 语句中插入了多少行的最佳方法是什么。我已经看过 SQL%BULK_ROWCOUNT 但我不确定它在下面的语句中是如何工作的。

是吗

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;

【问题讨论】:

你试过SQL%ROWCOUNT吗? docs.oracle.com/database/121/LNPLS/static.htm#LNPLS99956 大概是v_arc_act_plus_triggers1.COUNT?假设没有异常发生,等等。 没有例外,因为它只是从一个表直接复制到作为副本的存档表。 不确定 SQL%ROWCOUNT 在 FORALL 语句中是否有效?还是@a_horse_with_no_name 出于好奇,您为什么不直接使用insert into ... select ... 声明呢?它会比批量收集更高效。实际上,考虑一下,也许 MERGE 语句在这里效果最好。 【参考方案1】:

我没有检查,因为我没有什么要测试的,所以请原谅任何“缺少分号类型错误”,恐怕我无法进行性能检查。

您的代码似乎根据存档中不存在的情况选择要插入存档表的行。因此,只需使用基于 SELECT 的 INSERT,该 SELECT 受合适的 ROWNUM 值限制。一旦你提交,那么下一次循环它不会尝试获取已经归档的行,因为你刚刚提交它们。

我认为这应该与扩大插入物一样快,甚至更快,其优势在于它更简单 - Occams Razor 等等。

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;

【讨论】:

我会尝试上述方法并回复您

以上是关于Oracle PL/SQL 如何输出在 FORALL 语句中进行了多少次插入的主要内容,如果未能解决你的问题,请参考以下文章

如何使用其他 pl/sql 块在 Oracle db 中输出信息?

去掉 PL/SQL 函数末尾的逗号 [Oracle PL/SQL]

Oracle PL/SQL:如何使用可变数组作为输出参数执行过程?

创建在循环内输出不同名称的 Oracle PL/SQL 过程

如何在 Oracle 中调试 PL/SQL 集合的值?

有没有办法在 Oracle 中刷新 PL/SQL 的输出?