既存システムのコード解析してる中で、今まであまり利用して無かった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