Skip to main content

Overview

Mutation methods modify data in your database. All mutations can optionally return affected rows using .return() or .returnFirst().

insert

Insert one or more rows into the table.

Syntax

model.insert(data) => ModelInMutableResult

Parameters

data
TableInsert | TableInsert[]
required
Object (or array of objects) containing the data to insert.Must match the table schema. Optional columns can be omitted.

Return Type

Returns a ModelInMutableResult which extends Promise<void> with optional return methods:
  • .return() - Return all inserted rows
  • .returnFirst() - Return first inserted row

Examples

await userModel.insert({
  name: "Alex",
  email: "[email protected]",
  age: 25,
});

update

Update rows matching the current where conditions.

Syntax

model.update(data) => ModelInMutableResult

Parameters

data
Partial<TableInsert>
required
Object containing fields to update.All fields are optional - only provided fields will be updated.

Return Type

Returns a ModelInMutableResult with optional return methods.

Examples

await userModel
  .where({ id: esc(1) })
  .update({ name: "Updated Name" });
Always use .where() before .update() to specify which rows to update. Without a where clause, ALL rows will be updated.

delete

Delete rows matching the current where conditions.

Syntax

model.delete() => ModelInMutableResult

Return Type

Returns a ModelInMutableResult with optional return methods.

Examples

await userModel
  .where({ id: esc(1) })
  .delete();
Always use .where() before .delete() to specify which rows to delete. Without a where clause, ALL rows will be deleted.

upsert

Insert a row or update it if a conflict occurs on the target column(s).

Syntax

model.upsert({
  insert,
  update,
  target?,
  updateWhere?
}) => ModelInMutableResult

Parameters

insert
TableInsert
required
Data to insert if no conflict occurs.
update
Partial<TableInsert> | UpdateFunction
required
Data to update if a conflict occurs.Can be a plain object or a function receiving a context object with:
  • excluded(field) - Value from the INSERT attempt
  • inserted(field) - Existing value in the table
target
Column | Column[]
Column(s) to check for conflicts. Defaults to primary key(s).
import * as schema from "./schema";

target: schema.user.email
// or
target: [schema.user.email, schema.user.username]
updateWhere
UpdateWhereFunction
Function to add additional WHERE conditions to the UPDATE clause.
updateWhere: (c) => ({
  updatedAt: esc.lt(c.excluded("updatedAt"))
})

Return Type

Returns a ModelInMutableResult with optional return methods.

Examples

import * as schema from "./schema";

await userModel.upsert({
  insert: { 
    name: "Alex", 
    email: "[email protected]", 
    age: 25 
  },
  update: { 
    name: "Alex Updated",
    age: 26
  },
  target: schema.user.email,
});

Return Methods

All mutation methods return a ModelInMutableResult which provides these chainable methods:

.return()

Return all affected rows.
const users = await userModel
  .insert([...])
  .return();
// users: User[]
Optionally specify which fields to return:
const users = await userModel
  .insert([...])
  .return({ id: true, name: true });
// Only id and name are returned

.returnFirst()

Return the first affected row (or undefined if no rows affected).
const user = await userModel
  .insert({ ... })
  .returnFirst();
// user: User | undefined
Optionally specify which fields to return:
const user = await userModel
  .insert({ ... })
  .returnFirst({ id: true, name: true });

.omit()

Exclude specific fields from the returned result (post-query, not SQL).
const user = await userModel
  .update({ secretField: "value" })
  .returnFirst()
  .omit({ secretField: true, password: true });
// secretField and password are excluded from result

.safe()

Wrap the result in a { data, error } object instead of throwing errors.
const result = await userModel
  .insert({ ... })
  .returnFirst()
  .safe();

if (result.error) {
  console.error(result.error);
} else {
  console.log(result.data);
}

Dialect Differences

PostgreSQL & SQLite

Natively support .returning() - all fields are returned efficiently:
const user = await userModel.insert({ ... }).returnFirst();
// Uses RETURNING clause

MySQL

Does not support RETURNING. Only returns primary key fields:
const result = await userModel.insert({ ... }).returnFirst();
// result: { id: number } - only primary key
For full row data, perform a follow-up query:
const { id } = await userModel.insert({ ... }).returnFirst();
const user = await userModel.where({ id: esc(id) }).findFirst();

Type Safety

All mutation methods are fully typed:
// ✅ TypeScript validates insert data
await userModel.insert({
  name: "Alex",    // ✅ Valid
  age: 25,         // ✅ Valid
  // invalid: 123  // ❌ Type error: unknown field
});

// ✅ Update data is partial
await userModel.update({
  name: "New Name", // ✅ Can update just one field
});

Notes

Mutation methods that modify the database always return Promise<void> unless you chain .return() or .returnFirst().
MySQL Limitation: .return() methods only return primary key values on MySQL. Use .findFirst() for full row data.

Build docs developers (and LLMs) love