mcpField
D
drizzle-orm

drizzle-orm

github.com/marcioaltoeData & databases068 installsUpdated today
Repository

About drizzle-orm

Drizzle ORM is an ORM for TypeScript applications to declare database schemas and run queries and data operations. It supports multiple SQL dialects and includes Drizzle Kit for managing migrations and browsing databases.

Key features

  1. 01Declare tables and column types
  2. 02Run CRUD, joins, and relational queries
  3. 03Support transactions, savepoints, and raw SQL
  4. 04Manage migrations with Drizzle Kit
  5. 05Browse databases visually

Use cases

  1. 01Define a database schema in a TypeScript project
  2. 02Query related data and run transactions
  3. 03Generate and apply database migrations
  4. 04Inspect a database and check migration consistency

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/marcioaltoe/skills --skill drizzle-orm

After installing, type/drizzle-ormin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

agents/
openai.yaml
references/
advanced-patterns.md
column-types-minor-dialects.md
connections.md
drizzle-seed.md
migrations.md
queries.md
relations.md
schema-mysql.md
schema-postgresql.md
schema-sqlite.md
schema-validation.md
transactions-and-batch.md

Details

From the project README

Drizzle ORM

~7.4kb minified+gzipped, zero dependencies, serverless-ready.

Quick Start

Install
# PostgreSQL
npm i drizzle-orm pg
npm i -D drizzle-kit @types/pg

# MySQL
npm i drizzle-orm mysql2
npm i -D drizzle-kit

# SQLite
npm i drizzle-orm better-sqlite3
npm i -D drizzle-kit @types/better-sqlite3

# Turso / LibSQL
npm i drizzle-orm @libsql/client
npm i -D drizzle-kit

# Bun SQL (PostgreSQL — zero extra deps)
bun add drizzle-orm
bun add -D drizzle-kit

# Bun SQLite (zero extra deps, sync APIs)
bun add drizzle-orm
bun add -D drizzle-kit
Config
// drizzle.config.ts
import { defineConfig } from "drizzle-kit";

export default defineConfig({
  dialect: "postgresql", // "postgresql" | "mysql" | "sqlite" | "turso" | "singlestore"
  schema: "./src/db/schema.ts",
  out: "./drizzle",
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  },
});
Schema
// src/db/schema.ts
import { pgTable, serial, text, integer, timestamp } from "drizzle-orm/pg-core";

export const users = pgTable("users", {
  id: serial().primaryKey(),
  name: text().notNull(),
  email: text().unique(),
  createdAt: timestamp().defaultNow(),
});

export const posts = pgTable("posts", {
  id: serial().primaryKey(),
  title: text().notNull(),
  content: text(),
  authorId: integer("author_id").references(() => users.id),
});
Connect & Query
import { drizzle } from "drizzle-orm/node-postgres";
import { eq } from "drizzle-orm";
import * as schema from "./schema";

const db = drizzle(process.env.DATABASE_URL!, { schema });

// select
const allUsers = await db.select().from(schema.users);

// insert
const [user] = await db.insert(schema.users)
  .values({ name: "Dan", email: "[email protected]" })
  .returning();

// update
await db.update(schema.users)
  .set({ name: "Daniel" })
  .where(eq(schema.users.id, 1));

// delete
await db.delete(schema.users).where(eq(schema.users.id, 1));

See references/connections.md for all provider setups (Neon, Turso, Supabase, D1, etc.).

Schema Declaration

Import table/column builders from the dialect-specific module:

// PG:     import { pgTable, serial, text, ... } from "drizzle-orm/pg-core";
// MySQL:  import { mysqlTable, int, varchar, ... } from "drizzle-orm/mysql-core";
// SQLite: import { sqliteTable, integer, text, ... } from "drizzle-orm/sqlite-core";
Common Column Types (PG)
TypeUsageNotes
serial()Auto-increment PKUse integer().generatedAlwaysAsIdentity() for new projects
integer()4-byte int
bigint({ mode: "number" })8-byte int"bigint" mode for >2^53
text()Unlimited text{ enum: [...] } for TS union
varchar({ length: n })Variable-length
boolean()true/false
timestamp()Date/time{ withTimezone: true }, mode: "date"
date()Calendar datemode: "date" for JS Date
json() / jsonb()JSON data.$type<T>() for typing
uuid()UUID.defaultRandom() for gen_random_uuid()
numeric({ precision, scale })Exact decimalReturns string by default
Constraint Modifiers
column.notNull()
column.default(value)
column.default(sql`now()`)
column.$defaultFn(() => createId())   // runtime default
column.$onUpdate(() => new Date())    // runtime on update
column.primaryKey()
column.unique()
column.references(() => other.id, { onDelete: "cascade" })
column.$type<CustomType>()            // branded types
Auto-map Casing
// drizzle.config.ts
export default defineConfig({
  casing: "snake_case", // camelCase TS keys -> snake_case DB columns
});

Full column type catalogs: PG | MySQL | SQLite | MSSQL/CockroachDB/SingleStore

CRUD Operations

All operators imported from "drizzle-orm":

import { eq, ne, gt, gte, lt, lte, and, or, not, like, ilike, inArray, between, isNull, sql } from "drizzle-orm";
Select
// basic
await db.select().from(users);

// partial + where
await db.select({ id: users.id, name: users.name })
  .from(users)
  .where(and(eq(users.role, "admin"), gt(users.age, 18)))
  .orderBy(asc(users.name))
  .limit(10).offset(20);

// aggregation
await db.select({ role: users.role, count: sql<number>`count(*)` })
  .from(users).groupBy(users.role).having(gt(sql`count(*)`, 5));
Insert
// single + returning
const [user] = await db.insert(users).values({ name: "Dan" }).returning();

// bulk
await db.insert(users).values([{ name: "A" }, { name: "B" }]);

// upsert (PG/SQLite)
await db.insert(users).values({ id: 1, name: "Dan" })
  .onConflictDoUpdate({ target: users.id, set: { name: "Dan" } });

// upsert (MySQL)
await db.insert(users).values({ id: 1, name: "Dan" })
  .onDuplicateKeyUpdate({ set: { name: "Dan" } });
Update / Delete
await db.update(users).set({ name: "Jane" }).where(eq(users.id, 1)).returning();
await db.delete(users).where(eq(users.id, 1)).returning();

Full queries reference: references/queries.md

Joins

// inner join
await db.select().from(users)
  .innerJoin(posts, eq(users.id, posts.authorId));

// left join
await db.select().from(users)
  .leftJoin(orders, eq(users.id, orders.userId));

// self-join with alias
import { alias } from "drizzle-orm/pg-core";
const parent = alias(users, "parent");
await db.select().from(users).leftJoin(parent, eq(users.managerId, parent.id));

Relations

V1 (Stable)
import { relations } from "drizzle-orm";

export const usersRelations = relations(users, ({ many }) => ({
  posts: many(posts),
}));

export const postsRelations = relations(posts, ({ one }) => ({
  author: one(users, { fields: [posts.authorId], references: [users.id] }),
}));
Relational Queries

Pass schema to drizzle to enable db.query:

const db = drizzle(url, { schema });

const result = await db.query.users.findMany({
  columns: { id: true, name: true },
  with: { posts: { with: { comments: true } } },
  where: (users, { eq }) => eq(users.id, 1),
  orderBy: (users, { desc }) => desc(users.createdAt),
  limit: 10,
});

const user = await db.query.users.findFirst({
  where: (users, { eq }) => eq(users.name, "Dan"),
  with: { posts: true },
});
V2 (Beta)
import { defineRelations } from "drizzle-orm";

export const relations = defineRelations(schema, (r) => ({
  users: { posts: r.many.posts() },
  posts: { author: r.one.users({ from: r.posts.authorId, to: r.users.id }) },
}));

V2 adds .through() for many-to-many without junction table boilerplate.

Full relations reference: references/relations.md

Drizzle Kit

CommandDescription
npx drizzle-kit generateCreate SQL migration files from schema diff
npx drizzle-kit migrateApply pending migrations
npx drizzle-kit pushSync schema directly (prototyping only)
npx drizzle-kit pullIntrospect DB → Drizzle schema
npx drizzle-kit checkValidate migration consistency
npx drizzle-kit studioVisual database browser

Full migrations reference: references/migrations.md

Transactions

const result = await db.transaction(async (tx) => {
  const [user] = await tx.insert(users).values({ name: "Dan" }).returning();
  await tx.insert(accounts).values({ userId: user.id, balance: 0 });
  return user;
});

Rollback with tx.rollback(). Nested transactions create savepoints.

Full reference: references/transactions-and-batch.md

Raw SQL

import { sql } from "drizzle-orm";

// typed expression
const lower = sql<string>`lower(${users.name})`;

// full raw query
await db.execute(sql`SELECT * FROM ${users} WHERE ${users.id} = ${id}`);

// placeholder for prepared statements
const prepared = db.select().from(users)
  .where(eq(users.id, sql.placeholder("id")))
  .prepare("get_user");
await prepared.execute({ id: 1 });

Reference Index

TopicFile
PostgreSQL column types, enums, schemas, indexes, views, RLSreferences/schema-postgresql.md
MySQL column types, enums, indexes, viewsreferences/schema-mysql.md
SQLite column types, indexes, viewsreferences/schema-sqlite.md
MSSQL, CockroachDB, SingleStore typesreferences/column-types-minor-dialects.md
Full query operators, advanced select, joins, CTEs, set ops, $countreferences/queries.md
Relations v1 + v2, relational queries APIreferences/relations.md
Drizzle Kit config, commands, programmatic migrationreferences/migrations.md
Transactions, savepoints, batch APIreferences/transactions-and-batch.md
drizzle-zod, drizzle-valibot, drizzle-typebox, etc.references/schema-validation.md
Connection setup per provider (Neon, Turso, Supabase, D1, PGlite, Expo, etc.)references/connections.md
Database seeding with drizzle-seed, versioningreferences/drizzle-seed.md
Read replicas, custom types, caching, ESLint, gotchas, drizzle-graphqlreferences/advanced-patterns.md

Comments

Markdown supported