insert
insert(&self, values: T) where T derives #[derive(SqlxInsert)] — a single-row INSERT
built from every named field of T, in declaration order.
#[derive(SqlxInsert)]
pub struct UserValues {
pub username: String,
pub email: String,
}
async fn insert(&self, values: UserValues) -> sqlx::Result<UserRow>;
Void vs. row-returning
The return type decides whether the written row is fetched back:
async fn insert(&self, values: EventValues) -> sqlx::Result<()>; // INSERT, nothing fetched back
async fn insert(&self, values: EventValues) -> sqlx::Result<EventRow>; // INSERT ... RETURNING *
Per-dialect SQL
Postgres/SQLite: INSERT INTO "table" (cols...) VALUES ($1, ...) RETURNING * — one
round-trip.
MySQL has no RETURNING. The row-returning form does INSERT → last_insert_id() →
SELECT * FROM table WHERE {key} = ?. {key} comes from an optional struct-level attribute on
the values struct, defaulting to id:
#[derive(SqlxInsert)]
#[key(user_id)]
pub struct UserValues { /* ... */ }
Field requirements
Every field must implement sqlx::Encode + sqlx::Type + Send. On MySQL, every field must also
implement Clone — this applies to the whole derived struct unconditionally (not just when you
call insert), because the upsert/upsert_all methods #[derive(SqlxInsert)] also generates
on the same struct (see upsert) need to keep a copy of whichever field ends up
being the runtime-selected conflict column, and that code is compiled as part of the struct's
impl block regardless of whether you ever call it.
See also
- insert_all — batch insert
- insert_or_ignore —
ON CONFLICT DO NOTHING/INSERT IGNORE - upsert / upsert_all — insert-or-update, same derive