有一个表A有1000万行数据,有字段(C1,C2),B表有100条数据有字段(C1,C2),现要更新A表中的字段C2为A.C2,条件是A.C1=B.C1,
A表中的C1是有重复的,也就是说更新的行数不等于100行,现在我想每10000行COMMIT一次,如何做呢?不用一个变量做计数的方式,
这样反而更慢,请问在过程中用BULK COLLECT和FORALL语句如何实现呢?

解决方案 »

  1.   

    FORALL 用 UPDATE 语句有限制:
        在FORALL循环中,UPDATE语句中的SET子句和WHERE子句中不能指向同一个集合,你可能需要获得另一个集合副本,以在WHERE子句指向新的名称。
    我有上传一个FORALL的用法小结  http://download.csdn.net/source/986611  你参考下吧,这问题是挺麻烦的。
      

  2.   

    用游标吧,
            --当10000条记录时commit
            IF c_cursor%ROWCOUNT / 10000 = 1 THEN
               COMMIT;
            END IF;
      

  3.   

    干嘛要分开来COMMIT呢?直接MERGE INTO就OK了嘛。
      

  4.   


    DECLARE
    TYPE T_B IS TABLE OF B%ROWTYPE INDEX BY VARCHAR2;
    V_B T_B;
    TYPE T_ROWID IS TABLE OF ROWID INDEX BY BINARY_INTEGER;
    V_ROWID T_ROWID;
    CURSOR CUR_A IS SELECT ROWID FROM A;
    BEGIN
    --把B置入索引表,改善效率
    FOR X IN CUR_B LOOP
     V_B(X.C1) := X.C2; 
    END LOOP;OPEN CUR_A;
    LOOP
    FETCH CUR_A BULK COLLECT INTO V_ROWID LIMIT 10000; --每次一万行的控制
     FORALL IN X IN 1..V_ROWID.COUNT 
      UPDATE A SET A.C2 = V_A(A.C1).C2  WHERE A.ROWID = V_ROWID(X);COMMIT;
    EXIT WHEN CUR_A%NOTFOUND;
    END LOOP;
    CLOSE CUR_A;
    END;上述代码只是一个可以参考的思路,未经过执行验证.谢谢!
      

  5.   

    你这说的更新A表的字段C2为A.C2 ,确定没写错,还是要更新为 B.C2, 理解为B.C2,从7楼的程序,修改如下:
    DECLARE
    TYPE T_ROWID IS TABLE OF ROWID INDEX BY BINARY_INTEGER;
    V_ROWID T_ROWID;
    TYPE T_BC2 IS TABLE OF B.C2%TYPE INDEX BY PLS_INTEGER;
    V_TBC2 T_BC2;
    CURSOR CUR_A IS SELECT A.ROWID,B.C2 FROM A WHERE A.C1 = B.C1;
    BEGINOPEN CUR_A;
    LOOP
    FETCH CUR_A BULK COLLECT INTO V_ROWID,V_TBC2 LIMIT 10000; --每次一万行的控制
    FORALL X IN V_ROWID.FIRST..V_ROWID.LAST
      UPDATE A SET A.C2 = V_TBC2(X) WHERE A.ROWID = V_ROWID(X);COMMIT;
    EXIT WHEN CUR_A%NOTFOUND;
    END LOOP;
    CLOSE CUR_A;
    END; 
    没测试,就做参考