查询不会更新所有行

时间:2017-12-22 15:28:09

标签: sql oracle plsql

有一张相当大的桌子,超过一千万行。它有列OBJ_ID,DATE_OF_CHANGE,USER。我添加了一个新列RECORD_ID,它现在是空的。 我需要更新它,因此RECORD_ID应该为OBJ_ID和DATE_OF_CHANGE提升数值。 我想出了这个:

 CREATE SEQUENCE REC_ID_SEQ
      START WITH 1
      INCREMENT BY 1
      CACHE 100;
    /
    CREATE OR REPLACE TRIGGER TRG_REC_ID_SEQ
      BEFORE INSERT ON T_HISTORY
      FOR EACH ROW
    BEGIN
      :NEW.RECORD_ID := REC_ID_SEQ.NEXTVAL;
    END;
    /

    DECLARE
       O_ID NUMBER := 0;
       S_DATE DATE := SYSDATE;
       HIST_NUM NUMBER := 0;       
       LOOP_COUNT NUMBER := 0;

    BEGIN

      FOR O IN (SELECT ROWID ROW_ID, D.* FROM T_HISTORY D ORDER BY D.OBJ_ID, D.DATE_OF_CHANGE)

      LOOP

          LOOP_COUNT := LOOP_COUNT + 1;
          IF O.OBJ_ID != O_ID OR O.DATE_OF_CHANGE!= S_DATE 
          THEN 
            HIST_NUM := HIST_NUM + 1; 
          END IF;


          UPDATE T_HISTORY T SET T.RECORD_ID = HIST_NUM WHERE T.ROWID = O.ROW_ID;     

          O_ID := O.OBJ_ID;
          S_DATE := O.DATE_OF_CHANGE; 

          IF LOOP_COUNT > 100000 THEN
          COMMIT; LOOP_COUNT := 0;
          END IF;

      END LOOP;
    END;
    /

但是当命令停止工作(没有错误)时,我发现大约有一半的行没有更新。我该怎么做正确的方法?

2 个答案:

答案 0 :(得分:2)

使用False命令和MERGE伪列作为主键的替代:

rowid

现场演示:http://sqlfiddle.com/#!4/aad05/2

答案 1 :(得分:1)

与@ krokodilko的解决方案类似,使用分析功能:

MERGE INTO t_history t
     USING (SELECT obj_id,
                   date_of_change,
                   ROW_NUMBER () OVER (ORDER BY obj_id, date_of_change) rn
              FROM t_history) r
        ON (t.obj_id = r.obj_id AND t.date_of_change = r.date_of_change)
WHEN MATCHED
THEN
   UPDATE SET t.record_id = r.rn;