0Pricing
SQL Academy · レッスン

UPSERT:ON CONFLICT DO UPDATE(PostgreSQL)

ON CONFLICT DO UPDATEで冪等な挿入を実装し、EXCLUDEDを使い、適切な競合対象を選択します。

「UPSERT:ON CONFLICT DO UPDATE(PostgreSQL)」はCoddyKit上の無料SQL Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSQL Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 SQL Academyコースには全4レッスンが含まれています。

UPSERTとは

UPSERTとは、存在しない場合はINSERTし、存在する場合はUPDATEする処理です。PostgreSQLではINSERT ... ON CONFLICTと記述します。

ON CONFLICT DO NOTHING

存在しない場合はINSERTし、重複している場合は何もせずにスキップします。

INSERT INTO users (email, full_name)
VALUES ('alice@example.com', 'Alice')
ON CONFLICT (email) DO NOTHING;

ON CONFLICT DO UPDATE

存在しない場合はINSERTし、存在する場合は指定した列をUPDATEします。

INSERT INTO users (email, full_name, last_login)
VALUES ('alice@example.com', 'Alice', NOW())
ON CONFLICT (email)
DO UPDATE SET
  full_name  = EXCLUDED.full_name,
  last_login = EXCLUDED.last_login;

EXCLUDED:提案された行

DO UPDATEの中で、EXCLUDED.colは「INSERTで書き込もうとした値」を意味します。何も付けない列名(またはusers.col)は既存の行を意味します。

ON CONFLICT (email)
DO UPDATE SET visits = users.visits + 1,
              last_seen = EXCLUDED.last_seen;

競合ターゲット

一意制約または主キーを指定する必要があります。

ON CONFLICT (email)             -- column with UNIQUE
ON CONFLICT (user_id, day)      -- composite UNIQUE
ON CONFLICT ON CONSTRAINT users_email_key   -- by name

条件付きUPSERT(DO UPDATEのWHERE)

条件を満たす場合にのみUPDATEします。

INSERT INTO inventory (product_id, qty)
VALUES (42, 5)
ON CONFLICT (product_id)
DO UPDATE SET qty = inventory.qty + EXCLUDED.qty
WHERE inventory.qty + EXCLUDED.qty <= 1000;

複数行のUPSERT

複数の行をINSERTし、各行を個別に処理します。

INSERT INTO page_views (path, day, count)
VALUES ('/home', CURRENT_DATE, 1), ('/about', CURRENT_DATE, 1)
ON CONFLICT (path, day)
DO UPDATE SET count = page_views.count + EXCLUDED.count;

UPSERTでのRETURNING

結果の行(INSERTされた場合でもUPDATEされた場合でも)を取得します。

INSERT INTO users (email, full_name)
VALUES ('alice@example.com', 'Alice')
ON CONFLICT (email) DO UPDATE
  SET full_name = EXCLUDED.full_name
RETURNING id, full_name;

冪等なワークフロー

UPSERTを使うと、リトライしても安全です。Webhookが2回発火しても、2回目の呼び出しでは重複行が作られず、同じ行がUPDATEされます。

MERGE(SQL標準、PG15以降)

PostgreSQL 15では、SQL標準のMERGEが追加されました。1つのステートメントでINSERT、UPDATE、DELETEを実行できます。

MERGE INTO users AS u
USING (VALUES ('alice@example.com','Alice')) AS src(email, name)
ON u.email = src.email
WHEN MATCHED THEN UPDATE SET full_name = src.name
WHEN NOT MATCHED THEN INSERT (email, full_name) VALUES (src.email, src.name);

UPSERTを使わない場合

UPSERTには一意制約が必要です。一意制約がない場合は、通常、SELECTを実行してからINSERTまたはUPDATEを行います。ただし、競合状態に注意し、適切なロックを使用してトランザクションで囲んでください。

まとめ

ON CONFLICTは、PostgreSQLで利用できる、明確でアトミックなUPSERTです。

  • 「存在しない場合にINSERT」にはDO NOTHINGを使用します
  • 本来のUPSERTにはDO UPDATEを使用します
  • EXCLUDEDは提案された行を表します
  • 必ず競合ターゲットを指定します

理解度チェック

ON CONFLICT (email) DO UPDATE SET last_login = EXCLUDED.last_loginにおいて、EXCLUDEDは何を指しますか。

よくある質問

「UPSERT:ON CONFLICT DO UPDATE(PostgreSQL)」レッスンは無料ですか?

はい。「UPSERT:ON CONFLICT DO UPDATE(PostgreSQL)」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、SQL Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 SQL Academyコースには全4レッスンが含まれています。

「UPSERT:ON CONFLICT DO UPDATE(PostgreSQL)」で何を学びますか?

ON CONFLICT DO UPDATEで冪等な挿入を実装し、EXCLUDEDを使い、適切な競合対象を選択します。 ブラウザで直接実行するハンズオンコードでSQL Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

SQL Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSQL Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「UPSERT:ON CONFLICT DO UPDATE(PostgreSQL)」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSQL Academyレッスンでコードを書いて実行できますか?

はい。すべてのSQL Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. 複数行のINSERT
  2. UPSERT:ON CONFLICT DO UPDATE(PostgreSQL)
  3. FROMとJOIN形式のUPDATE
  4. USING付きDELETEと安全なパターン
← SQL Academyに戻る