Skip to main content
DuckDB supports INSERT … ON CONFLICT, and the Diesel backend exposes it through .on_conflict(...). Use it to make an insert idempotent (DO NOTHING) or to merge new data onto an existing row (DO UPDATE). Verified in the crate’s tests/crud_dsl.rs.

DO NOTHING — idempotent insert

Skip the row silently when it would collide on the given target column(s):
The affected-row count is 0 when the conflict caused the row to be skipped.

DO UPDATE — merge on conflict

On a collision, update the existing row. The excluded(...) helper references the proposed row (the values that would have been inserted):
excluded comes from Diesel’s own diesel::upsert module. You can mix excluded(...) references with literals and column references in the SET clause, exactly like a normal update.
Pull the merged result straight back with .returning(...) — RETURNING works after ON CONFLICT:
The conflict target (.on_conflict(products::id)) must correspond to a PRIMARY KEY or UNIQUE constraint in DuckDB, as with any ON CONFLICT statement.

See also

Insert

The base insert builder.

RETURNING

Read the merged row back.

Update

The SET-clause mechanics do_update reuses.

Transactions

Batch many upserts atomically.