Oracle:创建记录列历史记录

时间:2017-12-14 15:03:37

标签: oracle oracle11g

通常,捕获历史记录的最佳解决方案是创建一个触发器,该触发器在更新到历史记录表时获取记录的快照但是:

1。)我的表包含60列,但我想只捕获10个列的历史记录。

2。)来自数据源的数据带有提交日期,但未在目标表中捕获。根据源发送的提交日期而不是基于当前的sysdate来捕获历史记录。

3.)我们可以控制选择,更新过程。

建议的解决方案:

我们创建了一个函数,如下所示

In(Primary Key, Submit_Date, Column_Name, Old Value, New Value)
PRAGMA AUTONOMOUS_TRANSACTION;

Fetch max(Submit_date) From History using PK;

If max_Submit_date is Null: 
    Insert in History using PK, 01-01-1700 as Submit date, Column Name, Old_Value;
    Insert into History using PK & Submit_date & new Value;
Elsif max_Submit_date = Submit_date
    Update History using PK & Submit_date with new Value;
Elsif max_Submit_date < Submit_date
    Insert into History using PK & Submit_date & new Value;
End if;

commit;

在选择要更新的数据时,我们添加了

select .... , 
DECODE(T.Column_VALUE_1,S.Column_VALUE_1,NULL,Function(PK,'COLUMN_NAME_1', S.Submit_Date, T.Column_VALUE_1, S.Column_VALUE_1)) XYZ,
DECODE(T.Column_VALUE_2,S.Column_VALUE_2,NULL,Function(PK,'COLUMN_NAME_2', S.Submit_Date, T.Column_VALUE_2, S.Column_VALUE_2)) XYZ,
From Source_Table S Join Target Table T Where ...

我可以看到解决方案不理想或不高效。请告知是否可以通过其他方式满足要求。

1 个答案:

答案 0 :(得分:0)

一种解决方案可能是使用MERGE INTO语句立即对所有记录执行此操作。由于您的submit_date属于insert并且也是比较,因此避免冲突的理想解决方案是在version表中包含History列,初始版本包含1和2,3, 4 ..等等后续版本。

而不是与解码和调用函数进行比较,您可以在where子句条件中排除所有此类记录。

MERGE INTO HISTORY h USING 
(

with m(pk,max_Submit_date) AS 
  ( select pk,submit_date,version 
           FROM HISTORY o where 
        version IN ( select MAX(version) max_version
                                     FROM HISTORY i where i.pk = o.pk ) ,

select .... PK, 
CASE WHEN m.max_Submit_date is Null 
 THEN 01-01-1700 
  WHEN  m.max_Submit_date <= s.Submit_date THEN 
s.Submit_date
END as Submit_date,
decode( m.max_Submit_date,NULL,T.Column_VALUE_1, S.Column_VALUE_1)
decode( m.max_Submit_date,NULL,T.Column_VALUE_2, S.Column_VALUE_2)
..
CASE WHEN m.max_Submit_date is Null
 THEN 1
   WHEN  m.max_Submit_date <= s.Submit_date
     THEN m.max_version + 1 new_version
    ELSE 
 m.max_version
END version 

From Source_Table S Join Target Table T 
JOIN m ON m.pk = s.pk 
Where ..

( T.Column_VALUE_1 != S.Column_VALUE_1 ) OR
( T.Column_VALUE_2 != S.Column_VALUE_2 ) OR
..
..


) cur

ON ( cur.pk = h.pk and h.version = cur.version )

WHEN MATCHED THEN 
Update SET h.Submit_date = cur.Submit_date,
h.Column_VALUE_1 = s.Column_VALUE_1,
h.Column_VALUE_2 = s.Column_VALUE_2
..


WHEN NOT MATCHED THEN INSERT

INSERT (PK,submit_date,column_1,..) VALUES (..);