drizzle-plus
Add focused query-builder extensions and SQL helpers to Drizzle ORM without changing the way you already model tables or execute queries.
drizzle-plus fills a few practical gaps around Drizzle's relational query
builder. Its extensions add methods such as count() and updateMany();
its SQL helpers make common expressions and dialect-specific functions easier
to compose with TypeScript.
The package supports PostgreSQL, MySQL, and SQLite. Most query extensions are enabled with a dialect-specific import, while shared SQL helpers come from the root package.
Start here
- Getting started — install the package, enable an extension, and choose the right import path.
- Create rows — insert one or more rows with typed results.
- Upsert rows — insert or update rows based on a primary key or unique constraint.
- Build a paginated query — derive the next-page filter from a cursor and sort order.
- Compose a selection — build reusable, type-checked
findManyconfigs.
Features
Query extensions
These methods extend db.query.<table>. Each page includes the import that
activates the method and the behavior to check before using it.
| Feature | Use it when |
|---|---|
| Create | You need an insert operation with optional duplicate skipping. |
| Upsert | A conflict should update an existing row. |
| Update many | One update should affect multiple rows, optionally with a limit. |
| Count | You need a filtered row count. |
| Find unique | The filter identifies one row through a unique key. |
| Find many and count | A list screen needs both page data and the total count. |
| Cursor pagination | You need stable pagination without hand-writing cursor filters. |
| Query composition | You want to reuse and merge findMany options without executing them. |
Database and select helpers
These helpers extend db, tables, or the select builder.
| Feature | Use it when |
|---|---|
$select |
A plain object should become a typed db.select() selection. |
$values |
A small in-memory row set should become a SQL VALUES relation or CTE. |
| Aliases | A select or relational query needs to be used as a named subquery. |
| Recursive CTEs | A query needs to refer to its own result while it is being built. |
| Materialized CTEs | PostgreSQL should materialize or inline a CTE explicitly. |
$without |
A table's column selection should omit a few fields. |
fromSingle() |
Optional joins must still produce one placeholder row. |
withoutFrom() |
A select should contain expressions but no FROM clause. |
SQL building blocks
| Feature | Use it when |
|---|---|
caseWhen() |
A conditional SQL expression should remain type-aware. |
nest() |
A one-column query should become a scalar SQL expression. |
toSQL() |
A JavaScript value should be safely bound as SQL input. |
| Universal SQL functions | You need common numeric, text, date, or null-handling functions. |
| Dialect-specific functions | A database-specific JSON, UUID, cast, or string function is required. |
| Timestamps | A database-generated date or timestamp should decode as a JavaScript Date. |
Utilities and types
| Feature | Use it when |
|---|---|
orThrow() |
An empty query result should become an exception. |
| Merge query options | Reusable filters and selections need a type-safe merge. |
toSelection() |
A reusable plain object should become a select selection. |
| Types | A helper type should be derived from an existing relational query builder. |