⚡IntermediateCTEs

Upsert: INSERT ON CONFLICT and MERGE

Insert or update rows atomically using ON CONFLICT and the MERGE statement.

Overview

Upsert combines INSERT and UPDATE into one atomic operation. If the row doesn't exist, insert it; if it does (conflict on unique/PK), update it. PostgreSQL supports two syntaxes: INSERT ... ON CONFLICT (the original, widely used) and MERGE (SQL standard, added in PostgreSQL 15). ON CONFLICT DO UPDATE uses EXCLUDED to reference the proposed row values. ON CONFLICT DO NOTHING silently skips conflicting inserts.

Key Points

  • •INSERT ... ON CONFLICT (col) DO UPDATE SET col = EXCLUDED.col
  • •EXCLUDED refers to the row that was attempted to be inserted
  • •ON CONFLICT DO NOTHING silently skip duplicate rows
  • •MERGE (PG 15+): WHEN MATCHED THEN UPDATE / WHEN NOT MATCHED THEN INSERT
  • •Specify the conflict target: ON CONFLICT (col) or ON CONFLICT ON CONSTRAINT name
  • •Upsert is atomic no race condition between check and insert

Examples

INSERT ON CONFLICT and MERGE

-- Upsert: update score if user exists, insert if new
INSERT INTO user_scores (user_id, score)
VALUES (42, 100)
ON CONFLICT (user_id) DO UPDATE
  SET score = GREATEST(user_scores.score, EXCLUDED.score),
      updated_at = NOW();

-- MERGE (PostgreSQL 15+)
MERGE INTO inventory AS target
USING new_stock AS source ON target.product_id = source.product_id
WHEN MATCHED THEN
  UPDATE SET qty = target.qty + source.qty
WHEN NOT MATCHED THEN
  INSERT (product_id, qty) VALUES (source.product_id, source.qty);

Exercises

Write SQL to solve each exercise. Your progress is saved automatically.

Loading editor…

Completed: 0 / 5 exercises

Knowledge Check

Question 1 of 4

What does EXCLUDED refer to in ON CONFLICT DO UPDATE?