如何使用Drizzle ORM实现类似Django的自定义数据迁移?
Drizzle 实现自定义数据迁移的方法
Drizzle 虽然默认的drizzle-kit generate:pg只检测架构变更,但完全可以通过手动创建迁移文件的方式实现类似Django的自定义数据迁移,确保操作仅执行一次。以下是具体方案:
方案一:手动创建独立数据迁移文件
Drizzle 依赖__drizzle_migrations表跟踪已执行的迁移,每个迁移文件有唯一的时间戳前缀和哈希,只要遵循命名规则,就能实现单次执行:
- 找到你的Drizzle迁移目录(默认是
./drizzle) - 新建迁移文件,命名格式与自动生成的一致:
YYYYMMDDHHMMSS_描述.ts(例如20240520143000_add_initial_admin_user.ts) - 文件中导出
up(执行迁移)和down(回滚迁移)函数,使用Drizzle ORM API或原生SQL完成数据操作
示例代码:
import { sql } from "drizzle-orm"; import { pgTable, varchar, timestamp } from "drizzle-orm/pg-core"; // 假设你的用户表定义 const users = pgTable("users", { id: varchar("id").primaryKey(), name: varchar("name").notNull(), createdAt: timestamp("created_at").defaultNow(), }); export async function up(db: any) { // 插入初始数据,支持ORM方法或原生SQL await db.insert(users).values([ { id: "admin_001", name: "系统管理员" }, ]); // 也可以用原生SQL实现更复杂的逻辑 // await db.execute(sql` // INSERT INTO users (id, name) // VALUES ('admin_001', '系统管理员') // ON CONFLICT (id) DO NOTHING; // `); } export async function down(db: any) { // 回滚操作:删除插入的测试数据 await db.delete(users).where(sql`id = 'admin_001'`); }
创建完成后,执行drizzle-kit push:pg或通过Drizzle ORM的migrate方法运行迁移,该文件会被执行一次并记录到迁移表中,不会重复执行。
方案二:在架构迁移中嵌入数据操作
如果需要和架构变更同步执行数据操作,可以在自动生成的架构迁移文件的up函数末尾添加带条件判断的数据操作,避免重复执行:
export async function up(db: any) { // 自动生成的架构变更代码(例如创建users表) await db.execute(sql`CREATE TABLE users (...)`); // 条件插入数据,确保仅执行一次 await db.execute(sql` INSERT INTO users (id, name) SELECT 'admin_001', '系统管理员' WHERE NOT EXISTS (SELECT 1 FROM users WHERE id = 'admin_001'); `); }
这种方式适合和架构强关联的数据初始化,但建议优先使用方案一,保持架构变更与数据迁移的分离,便于维护。
注意事项
- 手动迁移文件的时间戳前缀必须大于已有的迁移文件,保证执行顺序正确
- 不要修改已执行过的迁移文件,否则会导致哈希校验失败,Drizzle会将其视为新迁移
down函数需实现反向操作,方便后续回滚测试
内容的提问来源于stack exchange,提问作者Janne
相关产品推荐
相关产品推荐

