2

BULKINSERTを使用してSQLデータベースにインポートするCSVファイルを毎週受け取ります。一時テーブルに挿入してから、新しいレコードを挿入し、変更されたレコードを更新することで、メインテーブルとマージします。コードは次のとおりです。

BULK INSERT dbo.temp
FROM 'C:\Users\Administrator\Documents\20120125.csv'
WITH (FIELDTERMINATOR = ',', ROWTERMINATOR = '\n' );

MERGE dbo.main AS TargetTable                            
USING dbo.temp AS SourceTable                    
ON (TargetTable.name = SourceTable.name)                
WHEN NOT MATCHED BY TARGET                              
    THEN INSERT (name, age, gender, father, mother, teacher, mathsrating, historyrating, sciencerating, englishrating)
        VALUES(SourceTable.name, SourceTable.age, SourceTable.gender, SourceTable.father, SourceTable.mother, SourceTable.teacher, SourceTable.mathsrating, SourceTable.historyrating, SourceTable.sciencerating, SourceTable.englishrating)
WHEN MATCHED                                            
    THEN UPDATE SET
        TargetTable.name = SourceTable.name,
        TargetTable.age = SourceTable.age,
        TargetTable.gender = SourceTable.gender,
        TargetTable.father = SourceTable.father,
        TargetTable.mother = SourceTable.mother,
        TargetTable.teacher = SourceTable.teacher,
        TargetTable.mathsrating = SourceTable.mathsrating,
        TargetTable.historyrating = SourceTable.historyrating,
        TargetTable.sciencerating = SourceTable.sciencerating,
        TargetTable.englishrating = SourceTable.englishrating;

DELETE FROM dbo.temp

私が達成したいのは、更新によって上書きされたレコードを「以前の」値とともに新しいテーブルに格納して、変更された内容の履歴を保持することです。私はSQLにかなり慣れていませんが、少し調べてみると、トリガーが取るべきアプローチかもしれないようですが、これにアプローチする方法についての提案を歓迎します。

ありがとう

マット

4

1 に答える 1

1

merge ステートメントには、影響を受ける行をテーブルに出力するか、クエリの結果として出力するoutput 句があります。

When Matched 部分で追加の基準を指定することもできます。この場合、すべての値が既存の行と同じ場合に行が更新されないようにするために使用します。(1 != Null)列がnull可能である場合、これは少し注意が必要Nullです。評価がマイナスになることはないと思いますが、評価IsNull(s.rating, -1) != IsNull(t.rating, -1)が変わったかどうかを確認することができます

出力句はクエリの結果になる可能性があるため、内部クエリとしてネストできます。これを使用しUpdateTimestampて、履歴テーブルに を追加しました。

例: http://sqlfiddle.com/#!6/1651a/2

null チェックが必要な理由の例: http://sqlfiddle.com/#!6/bd99b/2

Insert Into 
  history_table  
Select
  GetDate(), [name], age, gender, father, mother, teacher, 
  mathsrating, historyrating, sciencerating, englishrating
From (
  Merge
    dbo.main As t
  Using
    dbo.temp AS s
      On (t.[name] = s.[name])
  When Not Matched By Target Then
    Insert (
      [name], age, gender, father, mother, teacher, 
      mathsrating, historyrating, sciencerating, englishrating
    ) values (
      s.[name], s.age, s.gender, s.father, s.mother, s.teacher, 
      s.mathsrating, s.historyrating, s.sciencerating, s.englishrating
    )
  When Matched And -- assume ratings can't be negative, but can be null
    t.age != s.age Or
    t.gender != s.gender Or
    t.father != s.father Or
    t.mother != s.mother Or
    t.teacher != s.teacher Or
    IsNull(t.mathsrating, -1) != IsNull(s.mathsrating, -1) Or
    IsNull(t.historyrating, -1) != IsNull(s.historyrating, -1) Or
    IsNull(t.sciencerating, -1) != IsNull(s.sciencerating, -1) Or
    IsNull(t.englishrating, -1) != IsNull(s.englishrating, -1)
  Then Update
    Set
      t.[name] = s.[name],
      t.age = s.age,
      t.gender = s.gender,
      t.father = s.father,
      t.mother = s.mother,
      t.teacher = s.teacher,
      t.mathsrating = s.mathsrating,
      t.historyrating = s.historyrating,
      t.sciencerating = s.sciencerating,
      t.englishrating = s.englishrating
  Output
      $action as Action, deleted.*
  ) as Updates 
于 2012-11-23T20:39:31.463 に答える