【詳しく解説】SQL ServerにおけるUpsertの書き方(サンプル付き)

当ページのリンクには広告が含まれています。

【総まとめ】UPSERTとは?DBごとの違いは?」では、主要なDBごとの書き方をざっくり説明しました。

今回は、SQL Server(及びSQL Database)でのUpsertに焦点を絞り、深堀していきたいと思います。

参考までに、DataFrameからUpsertを生成するPython関数も紹介していますので、必要に応じてコピぺしてご利用下さい。

目次

SQL Server は MERGE ~ で Upsertを行う

SQL Server でUpsertを行う場合は、MERGE INTO ~ WHEN ~を使います。

MERGE文の構文イメージ図

MERGE INTO ~に更新先(インサート先)のテーブル名、 USING ~に更新元のテーブル名、ON ~ にユニークキーを指定します。

そして、WHEN MATCHED THEN ~ にキーが存在した場合の処理(通常はUpdate文)、WHEN NOT MATCHED THEN ~ にキーが存在しなかった場合の処理(通常は Insert文)を記述します。

また、任意の値を Upsert したい場合は、 USINGに続けて (select 値1,値2,・・・)と記述します。

、ユニーク制約に名前を付けると、少しだけ記述が簡単になります。

検証データ

本記事のUpsert文を実際に試してみたい場合は、以下のSQLを実行して下さい。

テーブル間でUpsertする

2つのテーブル同士のUpsertイメージ図

テーブル間でUpsertする場合は次のように記述します。

この時、テーブルAとテーブルBのどちらに所属する列名であるかが明確になるよう、エイリアス名(又はテーブル名)を列名の先頭に付与する必要があります。

ただし、insert (列名1,列名2,・・・)の列名だけは例外で、逆にエイリアス名を付けるとエラーになるのでご注意ください。

実は、以下の通り insert の部分については、少しだけ省略した書き方ができます。

下記は 省略した例です。

1行をUpsertする

1レコードのUpsertイメージ図

任意の値をUpsertしたい場合は、USING テーブル名 の代わりに、(select 列名1 AS 値1,・・・)と記述します。「1行だけの一時的なテーブルを作って、それを USINGに指定する」と考えると分かり易いでしょう。

下記は、サンプルテーブルに (1,'2023/01/01 09:00:00',10000,5) のデータをインサートし、レコードが既に存在していれば 数量(count)を 5に更新するサンプルです。

ON~に記述する結合条件が真なら MATCHED THEN ~を、偽なら NOT MATCHED THEN ~を実行してくれるため、テーブルBとは全く異なる値でUpdateやInsertを行うことも、やろうと思えば可能です。

例えば、キーが存在しなければ Insert 時に count を 5で登録し、キーが存在すれば count を 15で Updateするという事もできます。

通常は、テーブルAとテーブルBを同じ内容にするためのUpsertですから、直値をあちこち記述するのではなく、列名を使って更新すべき値を指定します。

このMERGE文は、USING 部分を除いて、テーブルBからテーブルAへUpsertする時と全く同じです。

下記は簡略化した時のサンプルですが、 USING (SELECT ~)の AS も省略しています。

複数行をまとめてUpsertする

SQL Serverでは、1回のInsert文で複数行(複数レコード)をまとめて登録する マルチインサート文が使えますが、Upsertについても同様のことが行えます。

ポイントは、using の部分を union でつなげるところです。こうすることによって、複数行を持つテーブルが一時的に出来たように見え、テーブル間のUpsertが実行できます。

尚、下図のように1回のUpsertの中で キーが重複するデータをInsertした場合、「PRIMARY KEY違反 〇〇〇は重複するキーを挿入できません」又は「同じ行に対してUPDATE又はDELETEが実行されました」というエラーになります。

UpsertでInsertだけ行う(Updateしない)

Upsertでなければインサート、あればなのもしない動作のイメージ画像

WHEN MATCHED THEN UPDATE SET ~ の記述をしなければ、Updateされません。

Pythonのサンプル

それでは、参考例としてDataFrameの値からUpsert文を生成するPythonのサンプルプログラムについてご紹介します。

使い方のサンプル

create_upsert にDataFrame、テーブル名、ユニークキーのリストを指定するだけで、Merge文を生成してくれます。

尚、下記サンプルで生成したUpsert文は、冒頭に紹介したサンプルテーブルに対して実行が可能です。

関数のソースコード

以下は、関数本体のソースコードになります。数値以外のデータ(文字列、日付)はシングルクォートで括る必要があるので、dtype が 'object' か否かで判断しています。

また、insert into ~ values ~ の values に渡すカラム値は、文字列に変換後、'nan'⇒NULL に置換しています。もし値に 'nan' が含まれるとNULLに変換されてしまう点にご注意下さい。

まとめ

今回はSQLServerのUpsertに焦点を絞って詳細を解説しました。

SQLServerでUpsertを行うには、Merge into ~ に更新先テーブル名、using ~に更新元テーブル名、on ~ に結合条件を記載します。そして、 when not matched then ~ にキーが存在しなかった処理(通常は insert文)、when matched then ~ にキーが存在した時の処理(通常はUpdate文)を記述します。

また、キーが存在した場合、Updateしたくないなら when matched then ~を省略することで実現できます。

SQLServerでUpsertが必要になった時は、是非この記事を参考にしてください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次