Upsert a conflicting row
A new record should be inserted, but an existing record with the same primary or unique key should receive updated values.
Drizzle ORM · Module
.onDuplicateKeyUpdate() adds MySQL duplicate-key upsert behavior to a Drizzle insert. MySQL automatically chooses conflicts from primary keys and unique indexes, while set defines the update values.
Call this method after an insert and provide a set object describing the columns to update when MySQL detects a duplicate primary-key or unique-index value. Because MySQL chooses the conflict target automatically, no target column is passed; assigning a column to itself can emulate doing nothing.
.onDuplicateKeyUpdate({ set: { column: value } })| Name | Type | Description |
|---|---|---|
config | object | Configuration object containing set, whose column-value mappings define the update applied after a duplicate-key conflict. |
An insert query configured to update the conflicting row when MySQL detects a duplicate key.
ON CONFLICT.set.import { sql } from 'drizzle-orm';
await db.insert(users)
.values({ id: 1, name: 'John' })
.onDuplicateKeyUpdate({ set: { name: 'John' } });
await db.insert(users)
.values({ id: 1, name: 'John' })
.onDuplicateKeyUpdate({ set: { id: sql`id` } });The first insert updates the conflicting row's name. The second performs a no-op update by assigning the id column to itself.
A new record should be inserted, but an existing record with the same primary or unique key should receive updated values.
A duplicate should be tolerated without changing stored data.
onDuplicateKeyUpdate do?onDuplicateKeyUpdate adds MySQL duplicate-key update behavior to an insert. Its set object specifies the values written when a primary key or unique index conflict occurs.
Follow-up: How does it choose the conflict target? MySQL automatically checks the table’s primary key and unique indexes, and any conflicting unique index can trigger the update.
The method accepts an object with a set property, such as { set: { name: 'John' } }. It is chained after insert(...).values(...).
Follow-up: Can the method target a named constraint? Not through this API as documented; MySQL determines targets automatically.
MySQL does not provide a direct do-nothing-on-conflict operation in this syntax. Drizzle’s documented workaround is assigning a column to itself, for example id: sql\id\.
Follow-up: Why is sql used? It expresses the SQL column reference so the generated update leaves that value unchanged.
insertvaluessqlON DUPLICATE KEY UPDATEON CONFLICT