SQL SERVER - MERGE でテーブルのデータを同期する

MERGE 文を使ってテーブルのデータを同期する

同じような構造の二つのテーブルがあって、そのデータを同期したいような時ありませんか?

具体的には次のような処理をしたい時です。 

変更元となるテーブルをソーステーブル、変更先のテーブルをターゲットテーブルとして、

  • ソーステーブルのデータがターゲットテーブルに存在する時は UPDATE
  • ソーステーブルのデータがターゲットテーブルに存在しない時は INSERT
  • ターゲットテーブルにしか存在しない時は DELETE

これらの処理を行うことによって、ターゲットテーブルのデータはソーステーブルのデータと同じなるはずです。


MERGE 文を使うと、この UPDATE、INSERT、DELETE の処理を一度に行うことができます。

今回は簡単な MERGE 文を使ってテーブルのデータを同期する方法をご紹介します。

MERGE 文で同時に挿入・更新・削除を行う

今回使う、シンプルな MERGE ステートメントの構文は次の通りです。

MERGE <target_table>
USING <table_source>
ON <merge_search_condition>  
WHEN MATCHED 
   THEN <merge_matched>
WHEN NOT MATCHED BY TARGET
   THEN <merge_not_matched_by_target>
WHEN NOT MATCHED BY SOURCE
   THEN <merge_not_matched_by_source>; 
  • <target_table>: ターゲット(変更先)のテーブル
  • <table_source>: ソース(変更元)のテーブル
  • <merge_search_condition>: マージの結合条件
  • <merge_matched>: ソーステーブルのデータがターゲットテーブルに存在する時に実行される句
  • <merge_not_matched_by_target>: ソーステーブルのデータがターゲットテーブルに存在しない時に実行される句
  • <merge_not_matched_by_source>: ターゲットテーブルにしか存在しない時に実行される句

他にもオプションや条件の追加、結果の出力などいろいろありますので、興味のある方はマイクロソフトの MERGE (Transact-SQL) のページでご確認ください。


では、上のマージ文を使って、違うデータベースにある Student テーブルのデータを同期してみましょう。

まずデータの準備をします。 Student テーブルが存在しない Test4 と Test5 というデータベースがある前提で、以下のスクリプトを実行して Student テーブルを作ります。

CREATE TABLE Test4.dbo.Student (
   StudentID INT NOT NULL PRIMARY KEY,
   FirstName VARCHAR(50) NULL,
   LastName VARCHAR(50) NULL,
   Birthday DATE NULL,
   Gender CHAR(1) NULL
);

INSERT INTO Test4.dbo.Student
  (StudentID, FirstName, LastName, Birthday, Gender)
 VALUES
  (1, 'Taro', 'Yamada', '1980-02-15', 'M'),
  (2, 'Hanako', 'Tanaka' ,'1979-12-30', 'F'),
  (3, 'Yuko', 'Suzuki', '1979-07-07', 'F'),
  (4, 'Takao', 'Sato', '1980-03-12', 'M'),
  (5, 'Hiroki', 'Takagi', '1979-04-05', 'M'),
  (6, 'Yuka', 'Kimura', '1981-03-27', 'F');
-----------------------------------------
CREATE TABLE Test5.dbo.Student (
   StudentID INT NOT NULL PRIMARY KEY,
   FirstName VARCHAR(50) NULL,
   LastName VARCHAR(50) NULL,
   Birthday DATE NULL,
   Gender CHAR(1) NULL
);

INSERT INTO Test5.dbo.Student
  (StudentID, FirstName, LastName, Birthday, Gender)
 VALUES
  (1, 'Taro', 'Yamamoto', '1980-02-15', 'M'),
  (2, 'Hanako', 'Tanaka' ,'1979-12-30', 'F'),
  (4, 'Takao', 'Sato', '1980-03-12', 'M'),
  (5, 'Hiroki', 'Takagi', '1979-05-04', 'M'),
  (7, 'Sakura', 'Aoyama', '1995-02-20', 'F');

SQL SERVER - MERGE でテーブルのデータを同期する 1


Test4 と Test5 の Student テーブルのレコードは次のようになります。

SELECT * FROM Test4.dbo.Student;
SELECT * FROM Test5.dbo.Student;

SQL SERVER - MERGE でテーブルのデータを同期する 2


MERGE を使って、Test4 データベースの Student テーブルのレコードが Test5 データベースの Student テーブルのレコードと同じになるように同期してみましょう。

この場合、Test4.dbo.Student がターゲットテーブル、Test5.dbo.Student がソーステーブルになります。

ターゲットテーブルとソーステーブルの結合条件は StudentID として、二つのテーブルを同期するクエリーは次の通りです。

MERGE Test4.dbo.Student AS T
USING Test5.dbo.Student AS S 
ON T.StudentID = S.StudentID
WHEN MATCHED
   THEN UPDATE 
      SET
         T.FirstName = S.FirstName,
         T.LastName = S.LastName,
         T.Birthday = S.Birthday,
         T.Gender = S.Gender
WHEN NOT MATCHED BY TARGET 
   THEN INSERT (StudentID, FirstName, LastName, Birthday, Gender)
            VALUES (S.StudentID, S.FirstName, S.LastName, S.Birthday, S.Gender)
WHEN NOT MATCHED BY SOURCE 
   THEN DELETE;

SQL SERVER - MERGE でテーブルのデータを同期する 3


同じ StudentID を持つレコードが存在する時は WHEN MATCHED の UPDATE 句が実行されます。(緑枠)

ソーステーブルと同じ StudentID を持つレコードがターゲットテーブルに存在しない場合は WHEN NOT MATCHED BY TARGET の INSERT 句が実行されます。(黄枠)

ターゲットテーブルに存在しない場合 StudentID を持つレコードがある場合は WHEN NOT MATCHED BY SOURCE の DELETE 句が実行され、ターゲットテーブルのレコードが削除されます。(赤線)

SQL SERVER - MERGE でテーブルのデータを同期する 4


上記の MERGE ステートメントを実行した後に、Test4 と Test5 データベースの Student テーブルのレコードを確認するとデータが同期されていますね。

SELECT * FROM Test4.dbo.Student;
SELECT * FROM Test5.dbo.Student;

SQL SERVER - MERGE でテーブルのデータを同期する 5

以上、MERGE 文を使って二つのテーブルのデータを同期する方法をご紹介しました。

© 2010-2024 SQL Server 入門