SQLのMERGEについて

既存システムのコード解析してる中で、今まであまり利用して無かったSQL文があったので覚書。

テーブルのデータを更新するにあたり、UPDATE•INSERTはガンガン使うのだが、MERGEは使った事が無かったので仕様を確認した。

以下のような2つのテーブルがあるとする。

例えば、テーブルBの内容をテーブルAに反映させるとして、Bと同じIDがAにあったら更新・無かったら挿入とする時、
ストアドプロシージャ等でIFを利用することで実装可能ではある。

IF EXISTS(SELECT * FROM Table_A as A INNER JOIN Table_B as B ON A.ID = B.ID)
    UPDATE Table_A AS A
         JOIN Table_B AS B ON A.ID = B.ID
    SET A.名称 = B.名称,
           A.金額  = B.金額
ELSE
 INSERT (ID, 名称, 金額) VALUES(B.ID, B.名称, B.金額)

MERGEを利用すれば、上記のようなストアドを1つのSQLにまとめる事が出来る。

MERGE INTO Tabel_A as A
	USING Table_B as B
	ON A.ID = B.ID
		WHEN MATCHED THEN
			UPDATE SET
				A.名称 = B.名称,
				A.金額  = B.金額
		WHEN NOT MATCHED THEN
			INSERT(ID, 名称, 金額) VALUES(B.ID, B.名称, B.金額);

上記のSQLを実行すると以下のような結果になる。

実行結果:


上記のSQLを分解して見てみたい。

MERGE INTO Tabel_A as A

テーブルAに対してMERGEを行う、という宣言。ターゲットテーブルともいう。
※ちなみに「as A」はエイリアス(別名)。このSQLではTable_AはAという名称で扱うよ宣言されている。

USING Table_B as B
ON A.ID = B.ID

テーブルAと内容を比較するテーブル(今回はテーブルB)を宣言している。ON句でテーブルを紐づける項目が記載されている。

WHEN MATCHED THEN
	UPDATE SET
		A.名称 = B.名称,
		A.金額  = B.金額

USINGで比較した結果、合致するデータがあった場合、Aの内容をBの内容で更新すると記載されている。

WHEN NOT MATCHED THEN
	INSERT(ID, 名称, 金額) VALUES(B.ID, B.名称, B.金額);

合致するデータが無かった場合、Bの内容をAに追加すると記載されている。

これでMERGEの記述は完了。


また、NOT MATCHEDの部分を少し変える必要があるがDELETEを追加することも出来る。

MERGE INTO Tabel_A as A
	USING Table_B as B
	ON A.ID = B.ID
		WHEN MATCHED THEN
			UPDATE SET
				A.名称 = B.名称,
				A.金額  = B.金額
		WHEN NOT MATCHED BY TARGET THEN
			INSERT(ID, 名称, 金額) VALUES(B.ID, B.名称, B.金額)

		WHEN NOT MATCHED BY SOURCE THEN
			DELETE;

実行結果:

WHEN NOT MATCHED BY TARGET THEN
	INSERT(ID, 名称, 金額) VALUES(B.ID, B.名称, B.金額)

最初のMERGEでもあったが「BY TARGET THEN」が追加されており、SOURCE(テーブルB)の内容がTARGET(テーブルA)に無かったら挿入すると記載されている。

WHEN NOT MATCHED BY SOURCE THEN
	DELETE;

今度は先ほどと逆でTARGET(テーブルA)の内容がSOURCE(テーブルB)に無かった場合の事を記載されている。
テーブルBにはもものレコードが無いので、テーブルAからももが削除される。



MicroSoft公式:
learn.microsoft.com