[Transact SQL] レコードが存在しない場合はレコードの挿入をレコードが存在した場合はレコードを更新するSQL - MERGE 文の利用 (SQLServerでのUPSERT文の利用)

このページのタグ:[SQL] [Transact SQL] [SQL Server]
SQLでレコードが存在しない場合はInsertしてレコードを追加し、レコードが存在していればそのレコードを更新したいことがあります。従来の方法では、select文で条件に合致するレコードがあるか検索し、検索結果があればそのレコードを更新し、なければレコードを追加する方法で処理できますが、実行するSQL文を減らし動作を高速化する方法としてMERGE文を利用できます。
この記事ではMERGE文を利用したレコードの追加、更新を紹介します。

概要

MERGE文を利用すると、条件に一致した場合とそうでない場合の処理を記述できます。

書式

以下の書式となります
MERGE INTO (テーブル名) AS (エイリアス名)
USING (ソース元の式)
ON (条件)
WHEN MATCHED THEN
UPDATE SET (列名)=(値), ....
WHEN NOT MATCHED THEN
INSERT ((列名), ...) VALUES ((値), ...);

注意

MERGE文は末尾が";"で終了する必要がありますので注意してください。

MERGE文の例を紹介します。

テーブル

下記のテーブルがある場合を想定します。
idnamecategorypricepoint

SQL1

以下のSQLを実行します。

merge into TestTable as A
using (select 'Penguin' as name , 'BOX' as category, 230 as price, 10 as point) as B
on (a.name = B.name)
when matched then
update set category=B.category, price=B.price, point=B.point
when not matched then 
insert (name, category, price, point) values (B.name, B.category, B.price, B.point);

実行結果1

SQLを実行すると下図の状態になります。レコードがなかったため、レコードが挿入されました。
idnamecategorypricepoint
1PenguinBOX23010

SQL2

続いて以下のSQLを実行します。
nameが'Penguin'で既に同じレコードがあるため、レコードを追加ではなく更新する処理になります。

merge into TestTable as A
using (select 'Penguin' as name , 'BOX' as category, 540 as price, 22 as point) as B
on (A.name = B.name)
when matched then
update set category=B.category, price=B.price, point=B.point
when not matched then 
insert (name, category, price, point) values (B.name, B.category, B.price, B.point);
解説
ON節で (A.name=B.name)となっているため、nameが一致していれば when matched then 節が実行され、update処理になります。一致していない場合は、when not matched then 節が実行されinsert処理になります。

実行結果2

nameが'Penguin'で既にあるレコードと一致しているため、レコードの更新処理が実行されました。price, pointの値が更新されています。
idnamecategorypricepoint
1PenguinBOX54022

補足

値が固定の場合は、using 節に何も指定せず、when matched thenやwhen not matched then 節に直接値を記述するSQLでも動作します。ただし、値を2か所に記述する必要があるため、先に紹介した using 節内に記述するほうがシンプルでミスも減ります。

merge into TestTable as A
using (select null as n) as B
on (a.name = 'Penguin')
when matched then
update set category='BOX', price=120, point=10
when not matched then 
insert (name, category, price, point) values ('Penguin', 'BOX', 120, 10);

登録日 :2014-11-06    最終更新日 :2015-01-10
このページのタグ:[SQL] [Transact SQL] [SQL Server]
Japanese
プライバシー    iPentecについて
iPentec all rights reserverd. (ISDC)