发布于: -/最后更新: -/3 分钟/

Drizzle ORM快速上手,数据库也能版本控制

摘要

Drizzle ORM 是一个 TypeScript 的数据库 ORM 框架,它允许开发者使用 TypeScript 定义 Schema 和查询语句。它支持 PostgreSQL 数据库,并且可以自动生成 SQL 迁移文件。Drizzle ORM 的优点包括:类型安全、直观的查询 API、透明的 Schema 和迁移文件。开发者可以使用 Drizzle ORM 来管理数据库 Schema 和数据,包括定义表结构、推送变更、读写数据等。Drizzle ORM 的核心理念是让开发者可以轻松地使用它,而无需学习额外的 Schema 语言。

大伙儿应该都喜欢把数据库相关的东西放在代码库里的感觉吧?反正我挺喜欢的,一切尽在掌控。

Drizzle ORM 就很对我胃口。它的 Schema 定义、查询语句,全都是 TypeScript——不用像 Prisma 那样学一门专门的 Schema 语言。自动生成的 SQL 迁移文件也是纯文本,可以直接 git diff,Code Review 时一目了然。

下面用 PostgreSQL 来上手一波。

安装

Bash
bun add drizzle-orm pg
bun add -D drizzle-kit @types/pg

配置

先准备好数据库连接字符串:

Bash
# .env
DATABASE_URL=postgresql://user:password@localhost:5432/mydb

然后创建 Drizzle 实例:

TypeScript
// src/db/index.ts
import { drizzle } from "drizzle-orm/node-postgres";

export const db = drizzle(process.env.DATABASE_URL!);

定义表结构

Drizzle 用链式语法定义表的字段和约束,写起来非常直观:

TypeScript
// src/db/schema.ts
import { integer, pgTable, varchar } from "drizzle-orm/pg-core";

export const usersTable = pgTable("users", {
  id: integer().primaryKey().generatedAlwaysAsIdentity(),
  name: varchar({ length: 255 }).notNull(),
  age: integer().notNull(),
  email: varchar({ length: 255 }).notNull().unique(),
});

推送变更

表定义好了,怎么同步到数据库呢?先配置一下 drizzle.config.ts

TypeScript
// drizzle.config.ts
import { defineConfig } from "drizzle-kit";

export default defineConfig({
  out: "./drizzle",           // 迁移文件输出目录
  schema: "./src/db/schema.ts",
  dialect: "postgresql",
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  },
});

Drizzle 提供两种同步方式:

方式一:Push(开发阶段)

Bash
bunx drizzle-kit push

简单粗暴,直接把 Schema 变更推送到数据库,不生成迁移文件。适合前期快速迭代,改了就推,非常高效。

方式二:Generate + Migrate(上线阶段)

Bash
bunx drizzle-kit generate  # 生成 SQL 迁移文件
bunx drizzle-kit migrate   # 执行迁移

生成的迁移文件会放在 ./drizzle 目录下,可以提交到 Git,方便追溯每次表结构变更。适合生产环境,变更可控、可回滚。

⚠️ 注意:如果你之前一直用 push,后来想切换到 generate + migrate,可能会报错说表已存在。这是因为数据库里没有迁移历史记录。解决方法是手动在数据库的迁移记录表里插入已有迁移文件的名称,让 Drizzle 知道这些迁移已经执行过了。

读写数据

Drizzle 的查询 API 设计得和写 SQL 一样直观:

TypeScript
import { eq } from "drizzle-orm";
import { db } from "./db";
import { usersTable } from "./db/schema";

// 利用类型推断获取插入类型,省得手写 interface
type NewUser = typeof usersTable.$inferInsert;

const user: NewUser = {
  name: "John",
  age: 30,
  email: "john@example.com",
};

// 插入
await db.insert(usersTable).values(user);

// 查询全部
const users = await db.select().from(usersTable);

// 条件查询
const john = await db
  .select()
  .from(usersTable)
  .where(eq(usersTable.email, "john@example.com"));

select().from().where(),就跟写 SQL 一样,完全没有学习门槛。而且全程类型安全,字段名拼错了 IDE 直接报红。

总之

Drizzle 的核心理念就是:如果你会写 SQL,你就会用 Drizzle

没有魔法、没有黑盒,Schema 和迁移文件都是你能看懂的代码和 SQL。对于喜欢掌控感的开发者来说,这种透明度真的很舒服。

正文结束