行が存在すればupdate、存在しなければinsertするmerge文

merge文はたまーに使う時があって、いざ書こうとすると忘れてたりします。 なので簡単な例をメモしておきます。

merge文の例

こんなテーブルがあったとして。

create table #Fruit(
    Name nvarchar(3),
    Price int,
    constraint PK_Fruit primary key(Name));

@nameで指定した名前の行が存在すればupdate、存在しなければinsertするmerge文がこちら(ストアドにしちゃってますが)。

create proc #UpsertFruit
    @name nvarchar(3),
    @price int
as
    merge #Fruit as Target
    using (values(@name, @price)) as Source(Name, Price)
        on Target.Name = Source.Name
    when matched then
        update set Price = Source.Price
    when not matched then
        insert values(Source.Name, Source.Price);

ざっくり言うと、

  • mergeには、追加か更新するテーブル(Target)
  • usingには、存在をチェックして追加か更新する値(Source)
  • onには、TargetとSourceの結合条件

って感じですかね。

あと、テーブル値コンストラクタも使ってます。valuesのところ。

実行してみる

こういったデータがある場合、

insert into #Fruit
values ('バナナ', 100), ('みかん', 120), ('りんご', 150);

/*
Name Price
---- -----------
バナナ  100
みかん  120
りんご  150
*/

次のクエリを実行すると、みかんの行は存在するのでupdateになります。

exec #UpsertFruit @name = N'みかん', @price = 180;

/*
Name Price
---- -----------
バナナ  100
りんご  150
みかん  180
*/

さらに続けて次のクエリを実行すると、いちごの行は存在しないのでinsertになります。

exec #UpsertFruit @name = N'いちご', @price = 160;

/*
Name Price
---- -----------
バナナ  100
りんご  150
いちご  160
みかん  180
*/

参考