Skip to main content
DuckDB supports RETURNING on INSERT, UPDATE, and DELETE, and the Diesel backend exposes it through .returning(...). It is the way to read server-defaulted or server-computed values back from a write in a single round-trip — no follow-up SELECT.

How it works

Chain .returning(expr) on an insert/update/delete, then execute with a result-returning method instead of .execute: The .returning argument is a single column or a tuple of columns, mirroring .select — the Rust type you load into follows from it.

INSERT

UPDATE

DELETE

RETURNING * maps naturally to a #[derive(Queryable, Selectable)] struct: use .returning(Product::as_returning()) to pull a whole row back into a typed struct.
.returning(...) projects columns through the typed loader, so it reads standard types and the narrow unsigned-integer Duck* widths. The composite/semantic Duck* types (and HUGEINT/UHUGEINT) cannot be read this way — use diesel::sql_query("… RETURNING …") with a QueryableByName struct instead. See Type mapping.

See also

Insert

Where RETURNING is most used.

Upsert

RETURNING works after ON CONFLICT too.

Update

Return changed values.

Delete

Return removed values.