Create, update & delete
Insert, change, and remove rows with create, createMany, update, updateMany, delete, and deleteMany.
Use these methods for everyday writes. Single-row methods return the affected row (or null); batch methods return { count, data? }. For per-row values in one statement see updateEach, and for create-or-update see upsert.
create
Inserts one row and returns the created record:
const user = await client.users.create({
data: {
email: 'alice@example.com',
name: 'Alice',
active: true,
},
});createMany
Inserts many rows in one statement and returns { count, data? }:
const {
count, // number inserted
data, // inserted rows, when the driver supports RETURNING
} = await client.users.createMany({
data: [
{ email: 'a@example.com', name: 'A', active: true },
{ email: 'b@example.com', name: 'B', active: false },
],
});Skip duplicates
create and createMany accept skipDuplicates: true, or the column keys of the conflict target:
const maybeCreated = await client.users.create({
data: {
email: 'alice@example.com',
name: 'Alice',
active: true,
},
skipDuplicates: ['email'],
});With single-row create, a skipped insert returns null. With createMany, count only includes rows that were actually inserted.
Insert in chunks
Added in 0.3.0For large inputs, batchSize splits data into one INSERT per chunk so a single statement stays under driver parameter limits. count sums the inserted rows and data keeps input order. Hooks and plugins still run once per call. Chunks run one after another without an implicit transaction, the same as upsertMany; wrap the call in db.transaction(...) when all chunks must commit together. batchSize must be a positive integer.
const { count } = await client.users.createMany({
data: rows,
batchSize: 500,
skipDuplicates: true,
});update
Updates at most one matching row. The result is nullable (the target may not exist) and also exposes .throw().
When where matches several rows, only one of them is updated, on every dialect. Use updateMany to update every match.
const updated = await client.users.update({
where: { id: 1 },
data: { name: 'Alice Updated' },
});
if (!updated) {
throw new Error('Update target not found');
}An update whose data resolves to no values ({}, or every field undefined after plugins run) skips the UPDATE and returns the current row, or null when nothing matches.
updateMany
Added in 0.3.0
Updates every matching row and returns { count, data? }. data holds the updated rows:
const { count, data } = await client.users.updateMany({
where: { active: true },
data: { active: false },
}); // count: rows updatedPostgreSQL and SQLite return complete updated rows in data by default using native RETURNING. Pass a scalar select to narrow those rows, for example select: { id: true, active: true }. Relation projections are unsupported. When no row matches, the result is { count: 0 } with no data; MySQL always returns only { count }.
delete
Deletes at most one matching row and returns it (nullable, with .throw()). When where matches several rows, only one is deleted; use deleteMany to delete every match:
const deleted = await client.users.delete({
where: { id: 1 },
});deleteMany
Deletes every matching row and returns { count, data? }:
const { count, data } = await client.users.deleteMany({
where: { active: false },
}); // count: rows deletedOn PostgreSQL and SQLite, data contains the deleted rows, or the scalar fields requested by select, from native RETURNING. Empty results omit data. MySQL returns only { count }. Relation projections are unsupported.
Write relations
create, update, and upsert accept connect, disconnect, and set inside data, so you attach related rows without resolving foreign keys yourself:
const post = await client.posts.create({
data: {
title: 'Connected post',
author: { connect: { email: 'alice@example.com' } },
},
});See relation writes for every command, its rules, and the raw Drizzle equivalent.
Project write results
create, update, delete, upsert, createMany, updateEach, and upsertMany can project results. updateEach and upsertMany support select; the others support select and include:
const user = await client.users.create({
data: { email: 'writer@example.com', name: 'Writer', active: true },
select: { id: true, email: true },
});
// ^? { id: number; email: string }Edge cases
Reference
| Method | Writes | Returns | select / include |
|---|---|---|---|
create | one row | the row, or null when skipDuplicates skips it | both |
createMany | many rows | { count, data? } | both |
update | at most one row | the row or null, with .throw() | both |
updateMany | every match | { count, data? } | scalar select |
updateEach | listed rows, per-row values | { count, data? } | scalar select |
delete | at most one row | the row or null, with .throw() | both |
deleteMany | every match | { count, data? } | scalar select |
upsert | one row | the row | both |
upsertMany | many rows | { count, data? } | scalar select |