Drizzle ORM Cheat Sheet
Quick reference for Drizzle ORM — schema definition, queries, relations, migrations, and database operations. Type-safe SQL for TypeScript developers.
Setup & Configuration
Schema Definition (PostgreSQL)
Schema Definition (SQLite)
Select Queries
Insert / Update / Delete
Relations & Joins
Transactions & Raw SQL
Setup & Configuration
| npm i drizzle-orm | Install Drizzle ORM |
| npm i -D drizzle-kit | Install Drizzle Kit (migrations CLI) |
| npm i @neondatabase/serverless | Neon Postgres driver |
| npm i postgres | postgres.js driver |
| npm i better-sqlite3 | SQLite driver |
| npm i @libsql/client | Turso (libSQL) driver |
| npx drizzle-kit generate | Generate SQL migration files |
| npx drizzle-kit migrate | Run pending migrations |
| npx drizzle-kit push | Push schema directly (dev only) |
| npx drizzle-kit studio | Open Drizzle Studio (GUI) |
Schema Definition (PostgreSQL)
| import { pgTable, serial, text, integer, boolean, timestamp } from "drizzle-orm/pg-core" | Import column types |
| export const users = pgTable("users", { ... }) | Define a table |
| id: serial("id").primaryKey() | Auto-increment primary key |
| name: text("name").notNull() | Required text column |
| email: text("email").unique() | Unique constraint |
| age: integer("age").default(0) | Integer with default value |
| active: boolean("active").default(true) | Boolean with default |
| createdAt: timestamp("created_at").defaultNow() | Timestamp with default now() |
| role: text("role", { enum: ["admin", "user"] }) | Enum-like text column |
| bio: text("bio") | Nullable text column (default) |
Schema Definition (SQLite)
| import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core" | Import SQLite types |
| export const users = sqliteTable("users", { ... }) | Define SQLite table |
| id: integer("id").primaryKey({ autoIncrement: true }) | Auto-increment PK |
| name: text("name").notNull() | Required text |
| createdAt: integer("created_at", { mode: "timestamp" }) | Timestamp as integer |
Select Queries
| const users = await db.select().from(usersTable) | Select all rows |
| db.select().from(users).where(eq(users.id, 1)) | Where clause (equals) |
| db.select({ name: users.name }).from(users) | Select specific columns |
| where(and(eq(users.role, "admin"), gt(users.age, 18))) | AND condition |
| where(or(eq(users.role, "admin"), eq(users.role, "mod"))) | OR condition |
| where(like(users.name, "%john%")) | LIKE pattern match |
| where(inArray(users.id, [1, 2, 3])) | IN array |
| where(isNull(users.deletedAt)) | IS NULL check |
| .orderBy(desc(users.createdAt)) | Order by descending |
| .limit(10).offset(20) | Pagination |
Insert / Update / Delete
| await db.insert(users).values({ name: "John", email: "[email protected]" }) | Insert one row |
| await db.insert(users).values([...]).returning() | Insert many, return inserted |
| .onConflictDoUpdate({ target: users.email, set: { name: "New" } }) | Upsert on conflict |
| .onConflictDoNothing() | Skip on conflict |
| await db.update(users).set({ name: "Jane" }).where(eq(users.id, 1)) | Update rows |
| await db.delete(users).where(eq(users.id, 1)) | Delete rows |
| await db.delete(users).where(lt(users.createdAt, cutoff)) | Delete with condition |
Relations & Joins
| export const usersRelations = relations(users, ({ many }) => ({ posts: many(posts) })) | One-to-many relation |
| export const postsRelations = relations(posts, ({ one }) => ({ author: one(users, { fields: [posts.authorId], references: [users.id] }) })) | Many-to-one relation |
| db.query.users.findMany({ with: { posts: true } }) | Query with relations (relational queries) |
| db.query.users.findFirst({ where: eq(users.id, 1), with: { posts: true } }) | Find one with relations |
| db.select().from(users).leftJoin(posts, eq(users.id, posts.authorId)) | Left join (SQL-like) |
| db.select().from(users).innerJoin(posts, eq(users.id, posts.authorId)) | Inner join |
Transactions & Raw SQL
| await db.transaction(async (tx) => { ... }) | Database transaction |
| tx.rollback() | Rollback transaction |
| import { sql } from "drizzle-orm" | Import sql template tag |
| db.execute(sql`SELECT * FROM users WHERE id = ${id}`) | Raw SQL query |
| sql`count(*)`.as("total") | SQL expression with alias |
| db.select({ count: sql |
Aggregate query |
Try It Live
Test these patterns with our free SQL Formatter. No signup needed.
Open SQL Formatter →
Step-by-Step Guide
Read Guide →