【发布时间】:2017-12-23 00:09:27
【问题描述】:
有相当大的表,超过 10 000 000 行。它有 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;
/
但是当命令停止工作(没有错误)时,我看到大约一半的行没有更新。我该如何以正确的方式做到这一点?
【问题讨论】:
-
这看起来真的很贵。为什么不只是
UPDATE <table> SET record_id = ROW_NUMBER() OVER (ORDER BY obj_id, date_of_change;让它撕裂。 -
在这种构造 @Kaushik 中使用
rowid非常好——它们不会改变,因为 Oracle 保证您的数据具有读取一致性视图。正如 JNevill 所说,使用集合操作可能更可取...... -
Kaushik Nayak,这张桌子没有PK。 JNevill,听起来很合理,我现在就试试!
-
很遗憾,JNevill 的想法行不通。 “ORA-30483:此处不允许使用窗口函数”。
-
看起来必须在oracle的子查询中完成。
UPDATE t1 SET record_id = t1.RowNum FROM (SELECT obj_id_id, date_of_change, ROW_NUMBER() OVER (ORDER BY obj_id, date_of_change) AS rowNum FROM table) t1或类似的东西。