Skip to content
PHP2Shell: The PHP Bug
Akshay Thakare

Upserts with Delta Lake MERGE

Write idempotent upserts with MERGE INTO, handle duplicate source keys, apply deletes from CDC and avoid rewriting the whole table.

DatabricksIntermediate2 min readUpdated 11 Oct 2026

The basic upsert

SQL.sql
MERGE INTO silver.customers AS t
USING updates AS s
ON t.customer_id = s.customer_id
WHEN MATCHED AND s.updated_at > t.updated_at THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *;

The updated_at condition makes it safe to replay: an older change never overwrites a newer one.

Deduplicate the source first

MERGE fails when several source rows match the same target row. Keep the latest per key before merging:

SQL.sql
CREATE OR REPLACE TEMP VIEW updates AS
SELECT * FROM staged_changes
QUALIFY ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY updated_at DESC) = 1;

Deletes from CDC

SQL.sql
MERGE INTO silver.customers t
USING updates s ON t.customer_id = s.customer_id
WHEN MATCHED AND s.op = 'DELETE' THEN DELETE
WHEN MATCHED AND s.updated_at > t.updated_at THEN UPDATE SET *
WHEN NOT MATCHED AND s.op <> 'DELETE' THEN INSERT *;

Keep MERGE fast

  • Add a partition or date predicate to the ON clause so Delta reads only the affected files.
  • Run OPTIMIZE regularly. MERGE rewrites whole files, and smaller files mean less rewriting.
  • Enable deletion vectors where available, so updates mark rows instead of rewriting files.

Finished this note?

Share