Back

使用 Drizzle 进行模式优先的数据库开发

使用 Drizzle 进行模式优先的数据库开发

你的 TypeScript 类型说的是一回事,数据库说的却是另一回事。查询在运行时失败,你只能调试那些本不应该存在的不匹配问题。

使用 Drizzle 进行模式优先的数据库设计,通过让 TypeScript 代码成为唯一的真实来源来解决这个问题。你的模式定义同时驱动应用程序类型和数据库结构,消除了导致运行时意外的脱节。

本文将解释 Drizzle ORM 模式优先开发的工作原理、何时使用不同的迁移工作流程,以及需要避免的常见陷阱。

核心要点

  • Drizzle ORM 遵循代码优先的方法,其中 TypeScript 模式定义作为类型、查询和数据库结构的唯一真实来源。
  • Drizzle Kit 提供两种迁移路径:push 用于快速本地迭代,generate/migrate 用于可审计的、团队安全的部署。
  • 对于具有现有数据库的棕地项目,使用 drizzle-kit pull 来内省你的模式,然后再生成迁移以避免重新创建表。
  • Drizzle 的确定性命名与手动创建的数据库之间的约束名称不匹配可能会触发意外的迁移语句。

Drizzle 中模式优先的实际含义

Drizzle 从根本上是代码优先的。你在 TypeScript 中定义表、列和关系,该定义对下游的所有内容都具有权威性——查询、迁移和类型推断。

import { pgTable, serial, text, timestamp } from "drizzle-orm/pg-core"

export const posts = pgTable("posts", {
  id: serial().primaryKey(),
  title: text().notNull(),
  content: text(),
  createdAt: timestamp().defaultNow(),
})

这个模式文件具有双重用途。Drizzle ORM 使用它进行类型安全的查询。Drizzle Kit 使用它来生成或应用数据库更改。

这里的”模式优先”一词意味着你的 TypeScript 定义是主导。数据库跟随其后。

代码优先 vs 数据库优先:理解区别

传统的数据库优先工作流将数据库视为权威。你手动创建表或使用 SQL 脚本,然后从现有结构生成应用程序代码。

代码优先和数据库优先的比较经常混淆这些术语。在 Drizzle 的上下文中:

  • 代码优先:你的 TypeScript 模式驱动数据库更改
  • 数据库优先:你使用 drizzle-kit pull 将现有数据库结构拉取到 TypeScript 中

Drizzle 两者都支持。对于绿地项目,代码优先通常更简洁。对于棕地场景——加入一个具有现有数据库的项目——通过 pull 进行内省可以让你快速开始。

Drizzle Kit 工作流程:Push vs Generate

Drizzle Kit 为将模式更改应用到数据库提供了两条主要路径。

使用 Schema Push 进行快速迭代

npx drizzle-kit push

Push 将你的模式与数据库进行比较并直接应用更改。没有迁移文件。没有审查步骤。

这适用于:

  • 个人项目
  • 早期原型设计
  • 可以重新创建的本地开发数据库

权衡是可见性。你不会有什么时候更改了什么的记录。

为团队安全生成迁移

npx drizzle-kit generate
npx drizzle-kit migrate

generate 创建 SQL 迁移文件。migrate 应用它们。这些文件存在于版本控制中,创建审计跟踪。

这种方法适合:

  • 需要审查更改的团队环境
  • 需要回滚能力的生产部署
  • 需要更改文档的合规场景

这两种方法都不是普遍正确的。Drizzle Kit 工作流程根据你的上下文适应两者。

配置 Drizzle Kit

你的 drizzle.config.ts 告诉 Drizzle Kit 在哪里找到模式和存储迁移:

import { defineConfig } from "drizzle-kit"

export default defineConfig({
  dialect: "postgresql",
  schema: "./src/db/schema.ts",
  out: "./drizzle/migrations",
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  },
})

Drizzle 支持主要的 SQL 数据库,包括 PostgreSQL、MySQL 和 SQLite/libSQL,还有诸如 MSSQL 和 CockroachDB 等新兴方言。配置在不同数据库之间基本保持一致——只有方言和特定于驱动程序的选项会改变。

需要避免的常见陷阱

使用 Drizzle 进行模式优先开发并非没有摩擦点。

现有表需要仔细处理。 如果你在具有现有表的数据库上采用 Drizzle,你的第一次 generate 可能会生成试图重新创建所有内容的迁移。首先使用 pull 将你的模式文件与实际情况同步。

内省可能产生嘈杂的差异。 从数据库拉取可能包括与你手动编写的不同的约束名称或默认值。即使没有实质性的更改,后续的生成也可能将这些标记为更改。

约束名称不匹配会导致意外迁移。 Drizzle 确定性地生成约束名称。如果你的数据库有不同的名称(来自手动创建或其他工具),你会看到重命名约束的 ALTER 语句,而不会改变行为。

运行时迁移需要错误处理。 如果你在部署期间以编程方式应用迁移,请将它们包装在适当的错误处理中。部署中途失败的迁移可能会使数据库处于不一致的状态。

模式优先何时改善你的工作流程

Drizzle ORM 模式优先开发在以下情况下表现出色:

  • 你希望在编译时保证查询与模式匹配
  • 多个开发人员需要协调数据库更改
  • 你正在部署到边缘或无服务器环境,其中包大小很重要
  • 你更喜欢类似 SQL 的语法而不是抽象的查询构建器

Drizzle Studio 通过可视化界面补充此工作流程,用于浏览数据和针对你的模式测试查询。

结论

从你的模式文件开始。定义与你的领域匹配的表。在本地迭代时使用 push,然后在涉及团队成员或部署到生产环境之前切换到 generatemigrate

目标不是永远选择一个工作流程——而是理解权衡,以便为开发的每个阶段选择正确的工具。

常见问题

可以。运行 drizzle-kit pull 来内省你的现有数据库并生成匹配的 TypeScript 模式。这可以避免破坏性迁移。一旦你的模式文件反映了当前的数据库状态,你就可以开始使用 generate 和 migrate 进行所有未来的更改,而不会有数据丢失的风险。

一旦你的项目超越了个人原型设计,就切换到 generate。一旦涉及其他开发人员或你正在部署到预发布或生产环境,迁移文件就会提供你所需的审计跟踪和审查流程。Push 最好保留用于可以安全重新创建数据库的本地开发。

支持。Drizzle 支持直接在模式中定义外键,并提供关系 API 来声明一对一、一对多和多对多关系。这些关系为关系查询 API 提供支持,它允许你以类型安全的方式获取嵌套数据,而无需编写原始 SQL 连接。

两者都是代码优先的 ORM,但它们在理念上有所不同。Prisma 使用自己的模式语言并从中生成客户端。Drizzle 在纯 TypeScript 中定义模式,让你直接控制 SQL 输出和更小的包大小。Drizzle 在设计上更接近 SQL,而 Prisma 抽象了更多内容。

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay