Query options
The full argument surface for reads, projections, ordering, pagination, filter operators, and metadata.
This page is the reference for the arguments accepted by reads and (where noted) writes.
Read arguments
Accepted by findMany, findFirst, findOne, and findUnique:
Prop
Type
count and exists accept only where, cursor, and meta.
findUnique is the strictest of the read helpers semantically, but it still accepts the same query-argument shape as the other reads. The main difference is intent: use it when the where clause targets a unique lookup.
Row locks
Locks control concurrent row access during reads. See the dedicated row locks page for the full guide, including dialect support, error handling, and transaction-only enforcement.
await client.transaction(async (tx) => {
return tx.users.findMany({
where: { id: { gt: 0 } },
lock: {
mode: 'update',
skipLocked: true,
},
});
});- Supported on PostgreSQL and MySQL read helpers only.
count,exists, and all write operations do not acceptlock.skipLockedandnoWaitare mutually exclusive.tablesis PostgreSQL-only.- General relation loading with
include/ relationselectis intentionally rejected whenlockis present.
Filter operators
Operators available inside where, by column type. A bare value means equals; null matches nullable columns.
| Column type | Operators |
|---|---|
| String | equals, in, notIn, contains, startsWith, endsWith, mode, not |
| Number / bigint / Date | equals, in, notIn, lt, lte, gt, gte, not |
| Boolean | equals, not |
| Logical | AND, OR, NOT |
| To-one relation | is, isNot |
| To-many relation | some, every, none |
mode is 'default' or 'insensitive' (case-insensitive string matching). See filters and relations for examples.
Projections
// select - narrows, scalars + relations
{ select: { id: true, author: { select: { name: true } } } }
// include - keeps all scalars, adds relations
{ include: { author: true } }
// relation counts - available only in include
{ include: { _count: { select: { comments: true } } } }A relation value can be true or a nested read-args object (with its own where, select, orderBy, take). See selecting fields.
Pagination arguments
paginate accepts everything above plus limit. Only limit, take, and skip control the page:
Prop
Type
There is no page or perPage input. It returns { data, pagination: { type, page, perPage, total, pageCount, hasNext, hasPrevious } }, where perPage is the resolved page size and page is Math.floor(skip / perPage) + 1.
cursor accepts everything above plus:
Prop
Type
Pass after or before, never both. Both take a cursor object, such as a previous nextCursor / previousCursor. Without orderBy, pages are ordered by primary key ascending.
It returns { data, pagination: { type, hasNext, hasPrevious, nextCursor, previousCursor } }. See pagination.
Write-specific arguments
Read args are only part of the API surface. The write methods add a few important options that deserve their own reference.
Single-row writes
| Method | Extra args |
|---|---|
create | data, skipDuplicates?, select?, include?, meta? |
update | where, data, select?, include?, meta? |
delete | where, select?, include?, meta? |
upsert | where, create, update, select?, include?, meta? |
Batch writes
| Method | Extra args |
|---|---|
createMany | data[], skipDuplicates?, select?, include?, meta? |
updateMany | where?, data, meta? |
updateEach | by, data[], update, where?, select?, onEmpty?, meta? |
deleteMany | where?, meta? |
upsertMany | data[], target, update, select?, batchSize?, where?, meta? |
updateEach details
Prop
Type
const { count } = await client.users.updateEach({
by: users.id,
data: [
{ id: 1, active: false },
{ id: 2, active: true },
],
update: {
active: (row) => row.active,
},
});upsertMany details
import { sql } from 'drizzle-orm';
await client.users.upsertMany({
data: [
{ email: 'a@example.com', name: 'A', active: true },
{ email: 'b@example.com', name: 'B', active: false },
],
target: ['email'],
update: (ctx) => ({
name: ctx.excluded.name,
active: ctx.excluded.active,
updatedAt: sql`now()`,
}),
batchSize: 1000,
where: sql`users.disabled = false`,
});update accepts four shapes:
'all'- an explicit column list
- an explicit update object
- a function receiving
{ excluded, sql, table }
target is a single column name ('email') or an array of column names (['email']). batchSize splits data into chunks and must be a positive integer, otherwise the call throws OPERATION_ERROR.
where must be a Drizzle SQL fragment. It is not the same as the normal structured where filter used by reads and single-row writes.