2017-12-14 2 views
0

の作成:)オラクル:通常歴史をキャプチャするための最良の解決策は、しかし、履歴テーブルに更新している間に、レコードのスナップショットを取り、トリガー作成することです、レコード列の歴史

1.私のテーブルには、60個の列が含まれていますが、私はそのうちのわずか10人のために歴史を捉えたい。

2.)ソースからのデータには投稿日があり、ターゲットテーブルには取り込まれません。履歴の必要性は、それに基づいてキャプチャされる投稿日ソースによって送信され、現在のsysdateに基づいていません。

3.)私たちは、選択、更新プロセスを制御します。

提案された解決策:更新用データを選択しながら

は、我々は

私は解決策が理想的ではないことがわかります

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 ... 

を追加

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; 

以下のように機能を作成したり、効率的。他の方法で要件を満たすことができるかどうかアドバイスしてください。

答えて

0

MERGE INTOステートメントを利用して、すべてのレコードに対して同時に実行することができます。あなたのsubmit_dateはinsertの一部であり、比較もしているので、コンフリクトを回避する理想的な解決策は、Historyテーブルにversionという列を持つことです。最初のバージョンは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 (..); 
+0

我々は列ごとに個別に通常のテーブルと同一の履歴テーブル(私はそれを正しく解釈を願っ)しかし私の場合は履歴テーブルキャプチャのCOLUMN_NAME、NEW VALUE、古い値を持っています。 – pOrinG

+0

@pOrinG:それは履歴テーブルのデザインが悪いです。理想的には、ベーステーブルと同一で、複数のバージョンを持つ必要があります。ただ1つの新しい価値と1つの古い価値を保つだけでは、歴史とはみなされません。これは「リセット」テーブルのようなものです。そのため、ソリューションで提案されているように履歴テーブルを用意することが、より良い設計になるはずです。 –

+0

質問に記載されているように、私のテーブルには60個のカラムが含まれていますが、10個だけの履歴を取り込みたいと思います。私のすべての履歴要件はそうであり、不要なストレージ要件を作成したくありません。また、頻繁に変更されるいくつかの列(1-2など)がありますが、残りの部分はまれにしか更新されません。この場合は、スペースを食べるだけのベーステーブルのレプリカを作成するのは意味がありません。 – pOrinG

関連する問題