【あっぷさーと】

UPSERT とは?

最終更新:
💡 同じキーなら更新、なければ追加

追加するデータが一意キーなどで既存行と競合した場合は更新し、競合しなければ追加するデータベース操作。判定するキーや更新内容、書き方は製品ごとに確認します。

📌 このページのポイント
UPSERT:同じキーなら更新受け取ったデータ例:id = 7、名前 = ひよこ同じキーがある同じキーがないUPDATEINSERT既存行を更新新しい行を追加判定するキーと、更新する列を決める
一意キーが競合するかどうかで、更新か追加を行うイメージ。アプリ側でSELECTしてから分岐する手順を示す図ではありません。
ひよこ ひよこ
あれば更新、なければ追加するの?
ペンギン先生 ペンギン先生
そう。ただし「ある」の判定が大事だよ。例えばユーザーIDを一意にして、同じIDなら名前を更新し、新しいIDなら行を追加する。名前が似ているから同じ人、という判断を自動でしてくれるわけではないんだ。
ひよこ ひよこ
先にSELECTしてから、分岐しても同じ?
ペンギン先生 ペンギン先生
別々に確認と書き込みをすると、その間に別の処理が入ることがある。PostgreSQLのON CONFLICT DO UPDATEは、指定した競合の処理を一つの文で扱い、別のエラーがなければ追加か更新を原子的に行うよ。ただし権限や別の制約などのエラーまで無くすものではない。
ひよこ ひよこ
PostgreSQLではどう書くの?
ペンギン先生 ペンギン先生
例えばidが主キーのusers表なら、INSERT INTO users (id, name) VALUES (1, 'ひよこ') ON CONFLICT (id) DO UPDATE SET name = EXCLUDED.name; と書ける。EXCLUDED.nameは今回追加しようとした名前だよ。競合するキーと、上書きする列を明示するんだ。
ひよこ ひよこ
ほかのデータベースでも同じ?
ペンギン先生 ペンギン先生
MySQLはON DUPLICATE KEY UPDATEで、一意キーや主キーの重複時に更新する。SQLiteにもON CONFLICT DO UPDATEがあるよ。ただしSQLiteのINSERT OR REPLACEは、競合した既存行を削除してから追加する動作で、単なるUPDATEと同じではない。製品の仕様と、トリガーや関連データへの影響を確かめよう。
ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「UPSERT」って出てきたら「同じキーなら更新し、なければ追加するDB操作」と思えばだいたいOK!
📖 おまけ:英語の意味
「UPSERT(UPDATE + INSERT)」 = 更新と挿入を組み合わせた呼び名
💬 既存行への更新と、新しい行の挿入を組み合わせて扱います。SQLの書き方や競合時の条件はデータベース製品によって異なります。

参考資料

← 用語集にもどる