过了一段时间后,我想到了非常快速的一次通过合并声明来历史缓慢变化的维度类型2.
它在没有唯一约束的表上完美运行。
大多数情况下它也适用于具有唯一约束的表。但有时(通常当历史记录的变化较大时)我得到错误ORA-00001,唯一约束违规。当然,我知道有两种方法可行,但速度较慢。
我唯一的猜测是Oracle有时会在UPDATE之前执行INSERT,它会暂时复制TH_Valid_To_Date。
任何想法如何避免它(在保持主键的同时)?
来源表:
public Items(IEnumerable<Item> items) {
_items = items.ToList();
}
历史表:
CREATE TABLE TESTS
(
T_Key_1 NUMBER(38,0) DEFAULT -1 NOT NULL ENABLE /* */
,T_Key_2 NUMBER(38,0) DEFAULT -1 NOT NULL ENABLE /* */
,Text_Value VARCHAR2(100) /* */
,Number_Value NUMBER(38,0) DEFAULT -1 NOT NULL ENABLE /* */
,Amount NUMBER /* */
,CONSTRAINT T_PK PRIMARY KEY (T_Key_1, T_Key_2) /* Primární klíč */
)
;
合并:
CREATE TABLE TEST_HISTORY
(
T_Key_1 NUMBER(38,0) DEFAULT -1 NOT NULL
,T_Key_2 NUMBER(38,0) DEFAULT -1 NOT NULL
,Text_Value VARCHAR2(100)
,Number_Value NUMBER(38,0) DEFAULT -1 NOT NULL
,Amount NUMBER
,TH_Valid_From_Date DATE DEFAULT to_date('1000-01-01','yyyy-mm-dd') NOT NULL /* SCD2 - Start of validity of record. */
,TH_Valid_To_Date DATE DEFAULT to_date('3000-01-01','yyyy-mm-dd') NOT NULL /* SCD2 - End of validity of record. */
,CONSTRAINT TH_PK PRIMARY KEY (T_Key_1, T_Key_2, TH_Valid_To_Date) using index local
)
/** Physical Options **************************************************************************************************/
partition by range (TH_Valid_To_Date) interval (NUMTOYMINTERVAL (1, 'MONTH'))
(partition P_10000000 values less than (TO_DATE ('01-01-1000', 'DD-MM-YYYY')))
ENABLE ROW MOVEMENT
;
答案 0 :(得分:0)
我自己遇到了同样的问题:你不能同时插入和更新记录。 Oracle确定在首次执行连接时是插入还是更新记录。这是一个简化的测试用例,说明了这一点:
-- This is the table into which we will be merging data
CREATE TABLE merge_table
(
mt_col1 INTEGER NOT NULL
, mt_col2 INTEGER
);
-- Make mt_col1 unique
ALTER TABLE merge_table ADD (
UNIQUE (mt_col1)
USING INDEX);
-- This is the table from which we will be drawing the data
CREATE TABLE datasource_table
(
ds_col1 INTEGER
, ds_col2 INTEGER
);
-- Load up the data source with 10 rows (1-10)
INSERT INTO datasource_table (
ds_col1, ds_col2
)
SELECT ROWNUM r, ROWNUM r
FROM all_objects
WHERE ROWNUM < 11;
-- Create a duplicate record
INSERT INTO datasource_table (
ds_col1, ds_col2
)
VALUES (1, 1);
-- Create a record to be updated
INSERT INTO merge_table (
mt_col1, mt_col2
)
VALUES (2, 2);
COMMIT;
-- This merge will fail with a unique constraint violation because
-- an mt_col1 value of 1 does not exist. The datasource table contains
-- two entries for 1, so the merge will try to insert two mt_col1=1 records,
-- violating the unique constraint.
MERGE INTO merge_table dt
USING (SELECT ds_col1, ds_col2
FROM datasource_table) a
ON (a.ds_col1 = dt.mt_col1)
WHEN MATCHED
THEN
UPDATE SET mt_col2 = a.ds_col2 + 10
WHEN NOT MATCHED
THEN
INSERT (
mt_col1, mt_col2
)
VALUES (ds_col1, ds_col2);
-- ORA-00001: unique constraint (SYS_C0013990) violated
-- Delete one of the duplicate records and the merge succeeds
DELETE FROM datasource_table
WHERE ds_col1 = 1
AND ROWNUM < 2;
-- Merge is now successful
MERGE INTO merge_table dt
USING (SELECT ds_col1, ds_col2
FROM datasource_table) a
ON (a.ds_col1 = dt.mt_col1)
WHEN MATCHED
THEN
UPDATE SET mt_col2 = a.ds_col2 + 10
WHEN NOT MATCHED
THEN
INSERT (
mt_col1, mt_col2
)
VALUES (ds_col1, ds_col2);
-- 10 rows updated