FORALL插入目标表,然后从源表中删除FORALL

时间:2017-02-02 19:04:15

标签: sql oracle plsql forall bulk-collect

Cam下面没有问题吗?只要您将记录插入目标表,就可以从源表中删除该记录。显然这条记录在循环内存中,你能看到任何问题,还是可以用不同的方式完成。

我知道你们所有人都会说用APPEND做一个直接的SQL插入,然后截断源表。

我只是把问题扔出去,因为我很好奇。

PROCEDURE copy_records_back IS

  TYPE t_act_plus_triggers_copy1 IS TABLE OF act_plus_triggers_copy1%ROWTYPE;   v_act_plus_triggers_copy1 t_act_plus_triggers_copy1;

  CURSOR c_act_plus_triggers_copy1 IS   SELECT * FROM act_plus_triggers_copy;


BEGIN

  EXECUTE IMMEDIATE 'TRUNCATE TABLE act_plus_triggers1';

  OPEN c_act_plus_triggers_copy1;   LOOP
    FETCH c_act_plus_triggers_copy1 BULK COLLECT INTO v_act_plus_triggers_copy LIMIT 10000;  

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


    FORALL i IN 1..v_act_plus_triggers_copy.COUNT  
    DELETE FROM act_plus_triggers_copy
    where surr_id = v_act_plus_triggers_copy(i).surr_id

    COMMIT;     
    EXIT WHEN c_act_plus_triggers_copy1%NOTFOUND;

    END LOOP;   
CLOSE c_act_plus_triggers_copy1;

END copy_records_back;

1 个答案:

答案 0 :(得分:0)

如果两个表具有相同的列,则可以使用更简单的方法来完成此操作,而无需复制数据。您可以使用与两个表相同的列创建分区表,并且只创建一个分区。然后,您可以使用ALTER TABLE EXCHANGE PARTITION将表与分区交换,然后您可以以与目标表相同的方式交换分区(如果其中一个表已分区,则只需要进行一次交换)。如果数据需要更改表空间(或其他一些物理属性),您可以在最后发出ALTER TABLE MOVE来完成此任务。

在您的情况下,交换两个表的语句如下所示:

-- initialization (do only once)
CREATE TABLE temp_part_table PARTITION BY HASH (surr_id) (PARTITION single) AS
SELECT * FROM act_plus_triggers_copy WHERE 1=0
/
-- swapping act_plus_triggers_copy with act_plus_triggers1
ALTER TABLE temp_part_table EXCHANGE PARTITION single WITH TABLE act_plus_triggers1
WITHOUT VALIDATION
/
ALTER TABLE temp_part_table EXCHANGE PARTITION single WITH TABLE act_plus_triggers_copy
WITHOUT VALIDATION
/
ALTER TABLE temp_part_table EXCHANGE PARTITION single WITH TABLE act_plus_triggers1
WITHOUT VALIDATION
/

如果要交换两个表,则有三个交换。如果您知道temp_part_table(临时分区表)和act_plus_triggers1(目标表)最初都为空,则可以跳过第一个ALTER