数据库迁移生成器 database-migration

自动生成数据库迁移文件,包含模式变更和回滚功能,确保数据库操作的安全性和可回溯性。

后端开发 0 次安装 0 次浏览 更新于 3/4/2026

数据库迁移生成器

生成数据库迁移文件,包含模式变更和回滚功能,内置ToM验证以确保数据库操作安全。

何时调用

自动调用当用户提及:

  • “创建迁移”
  • “添加表格”
  • “修改模式”
  • “更改数据库”
  • “数据库迁移为[变更]”
  • “向[表格]添加列”
  • “重命名[表格/列]”

功能描述

  1. 检测迁移框架(Knex, Prisma, TypeORM, 原始SQL)
  2. 收集迁移需求
  3. 在生成前验证理解(ToM检查点 - 对于数据库变更至关重要)
  4. 带时间戳生成迁移文件
  5. 创建模式变更(上迁移)
  6. 创建回滚(下迁移)
  7. 验证迁移安全性
  8. 显示迁移摘要

执行步骤

第1步:检测迁移框架

检查项目中的迁移工具

# 检查Knex
if [ -f "knexfile.js" ] || [ -f "knexfile.ts" ] || grep -q '"knex"' package.json 2>/dev/null; then
  echo "Knex检测到"
fi

# 检查Prisma
if [ -f "prisma/schema.prisma" ]; then
  echo "Prisma检测到"
fi

# 检查TypeORM
if [ -f "ormconfig.json" ] || [ -f "ormconfig.ts" ] || grep -q '"typeorm"' package.json 2>/dev/null; then
  echo "TypeORM检测到"
fi

# 检查Drizzle
if grep -q '"drizzle-orm"' package.json 2>/dev/null; then
  echo "Drizzle检测到"
fi

框架检测结果

检测到:{FRAMEWORK}
迁移目录:{MIGRATION_PATH}
命名约定:{CONVENTION}

如果没有检测到框架

⚠️  未检测到迁移框架

选项:
1. 生成原始SQL迁移
2. 设置Knex(推荐灵活性)
3. 设置Prisma(推荐类型安全)

您的选择 [1-3]:

第2步:收集迁移需求

询问用户迁移细节

迁移名称:[例如,add_user_verification_columns]
变更类型:
  - create_table(新表)
  - add_column(添加到现有表)
  - modify_column(更改现有列)
  - drop_column(移除列)
  - rename(重命名表或列)
  - add_index(创建索引)
  - add_constraint(外键、唯一等)

目标表:[例如,users]

模式细节:[描述变更]

第2.5步:验证理解(ToM检查点 - 始终对数据库)[执行]

CRITICAL:这一步必须始终对数据库迁移执行。没有例外。

数据库迁移是高风险的 - 在生成前始终验证

显示验证

我理解您想要:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
迁移:{MIGRATION_NAME}
框架:{FRAMEWORK}(检测到)
类型:{CHANGE_TYPE}
目标:{TABLE_NAME}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

模式变更(UP):
{SCHEMA_CHANGE_PREVIEW}

回滚(DOWN):
{ROLLBACK_PREVIEW}

⚠️  数据库迁移影响生产数据
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

我做的假设:
- 列类型符合现有约定
- 索引将使用默认命名
- 不需要数据迁移(仅模式)

生成迁移文件?[Y/n]

永远不要跳过数据库迁移的验证 - 它们可能会导致数据丢失。

第3步:生成迁移文件

基于检测到的框架

Knex迁移

# 生成文件名
TIMESTAMP=$(date +%Y%m%d%H%M%S)
FILENAME="${TIMESTAMP}_${MIGRATION_NAME}.ts"

# 创建迁移文件
Write(
  file_path: "migrations/${FILENAME}",
  content: [knex迁移模板]
)

Knex模板

import { Knex } from 'knex';

export async function up(knex: Knex): Promise<void> {
  ${UP_MIGRATION}
}

export async function down(knex: Knex): Promise<void> {
  ${DOWN_MIGRATION}
}

Prisma迁移

# Prisma使用schema.prisma + migrate命令
# 更新schema.prisma中的新模型/字段
# 然后运行:npx prisma migrate dev --name ${MIGRATION_NAME}

显示Prisma工作流

检测到Prisma - 更新schema.prisma

1. 我将更新prisma/schema.prisma:
   ${SCHEMA_CHANGES}

2. 运行迁移:
   npx prisma migrate dev --name ${MIGRATION_NAME}

3. 生成客户端:
   npx prisma generate

TypeORM迁移

TIMESTAMP=$(date +%Y%m%d%H%M%S)
FILENAME="${TIMESTAMP}-${MIGRATION_NAME}.ts"

TypeORM模板

import { MigrationInterface, QueryRunner, Table } from 'typeorm';

export class ${MIGRATION_CLASS_NAME}${TIMESTAMP} implements MigrationInterface {
  public async up(queryRunner: QueryRunner): Promise<void> {
    ${UP_MIGRATION}
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    ${DOWN_MIGRATION}
  }
}

第4步:生成回滚逻辑

确保每个UP都有对应的DOWN

UP操作 DOWN操作
CREATE TABLE DROP TABLE
ADD COLUMN DROP COLUMN
ADD INDEX DROP INDEX
ADD CONSTRAINT DROP CONSTRAINT
RENAME RENAME(反向)
ALTER COLUMN ALTER COLUMN(反向)

针对破坏性操作的警告

⚠️  DOWN迁移中的DROP COLUMN将丢失数据!

列:{COLUMN_NAME}
类型:{COLUMN_TYPE}

如果此列有数据,请考虑:
1. 迁移前备份数据
2. 添加数据迁移步骤
3. 保留列但弃用

明白了吗?[Y/n]

第5步:验证迁移安全性

检查常见问题

迁移安全性检查:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ 定义了回滚(可以撤销更改)
✅ 没有DROP TABLE没有备份警告
✅ 没有在大表上ALTER没有考虑
⚠️  添加NOT NULL列 - 需要DEFAULT值
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

安全警告要检查

  • 添加NOT NULL没有DEFAULT(将在现有行上失败)
  • 带有数据的列删除
  • 重命名列(可能会破坏应用程序代码)
  • 添加唯一约束(如果存在重复则可能失败)
  • 大表更改(可能会锁定表)

第6步:显示迁移摘要

显示完成的迁移

✅ 迁移创建:{MIGRATION_NAME}

文件:{MIGRATION_PATH}/{FILENAME}
框架:{FRAMEWORK}
时间戳:{TIMESTAMP}

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

模式变更:
┌─────────────────────────────────────────────┐
│ UP(应用)                                  │
├─────────────────────────────────────────────┤
│ {UP_MIGRATION_SUMMARY}                      │
└─────────────────────────────────────────────┘

┌─────────────────────────────────────────────┐
│ DOWN(回滚)                             │
├─────────────────────────────────────────────┤
│ {DOWN_MIGRATION_SUMMARY}                    │
└─────────────────────────────────────────────┘

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

运行迁移:
{RUN_COMMAND}

测试回滚:
{ROLLBACK_COMMAND}

后续步骤:
1. 审核迁移文件
2. 在开发数据库上测试
3. 运行迁移:{RUN_COMMAND}
4. 验证模式变更
5. 提交迁移文件

模式变更模板

创建表格(Knex)

export async function up(knex: Knex): Promise<void> {
  await knex.schema.createTable('${TABLE_NAME}', (table) => {
    table.uuid('id').primary().defaultTo(knex.raw('gen_random_uuid()'));
    ${COLUMN_DEFINITIONS}
    table.timestamps(true, true);
  });
}

export async function down(knex: Knex): Promise<void> {
  await knex.schema.dropTableIfExists('${TABLE_NAME}');
}

添加列(Knex)

export async function up(knex: Knex): Promise<void> {
  await knex.schema.alterTable('${TABLE_NAME}', (table) => {
    table.${COLUMN_TYPE}('${COLUMN_NAME}')${MODIFIERS};
  });
}

export async function down(knex: Knex): Promise<void> {
  await knex.schema.alterTable('${TABLE_NAME}', (table) => {
    table.dropColumn('${COLUMN_NAME}');
  });
}

添加索引(Knex)

export async function up(knex: Knex): Promise<void> {
  await knex.schema.alterTable('${TABLE_NAME}', (table) => {
    table.index(['${COLUMN_NAME}'], '${INDEX_NAME}');
  });
}

export async function down(knex: Knex): Promise<void> {
  await knex.schema.alterTable('${TABLE_NAME}', (table) => {
    table.dropIndex(['${COLUMN_NAME}'], '${INDEX_NAME}');
  });
}

框架特定命令

Knex

# 运行待处理迁移
npx knex migrate:latest

# 回滚最后一批
npx knex migrate:rollback

# 运行特定迁移
npx knex migrate:up ${MIGRATION_NAME}

# 检查状态
npx knex migrate:status

Prisma

# 创建并应用迁移
npx prisma migrate dev --name ${MIGRATION_NAME}

# 在生产中应用
npx prisma migrate deploy

# 重置数据库(仅限开发)
npx prisma migrate reset

# 检查状态
npx prisma migrate status

TypeORM

# 运行待处理迁移
npx typeorm migration:run

# 回滚上一个迁移
npx typeorm migration:revert

# 从实体生成迁移
npx typeorm migration:generate -n ${MIGRATION_NAME}

# 显示迁移
npx typeorm migration:show

错误处理

框架未检测到

⚠️  项目中未检测到迁移框架

请先设置迁移框架:
- Knex:npm install knex && npx knex init
- Prisma:npm install prisma && npx prisma init
- TypeORM:npm install typeorm && 创建ormconfig

迁移名称冲突

⚠️  已存在类似名称的迁移

现有:20251209_add_users_table.ts
请求:add_users_table

选项:
1. 使用不同名称
2. 添加版本后缀(add_users_table_v2)
3. 检查现有迁移是否足够

您的选择 [1-3]:

验证失败

❌ 迁移验证失败

问题:
- 列'status'是NOT NULL但没有DEFAULT
- 表'orders'不存在(在外键中引用)

在生成迁移之前修复这些问题。

成功标准

迁移成功时:

  • [ ] 迁移文件生成带有唯一时间戳
  • [ ] 遵循框架约定
  • [ ] UP迁移正确创建/修改模式
  • [ ] DOWN迁移完全回滚更改
  • [ ] ToM验证通过(用户确认理解)
  • [ ] 安全检查通过
  • [ ] 显示运行迁移命令

最佳实践

命名约定

  • create_users_table - 新表
  • add_email_to_users - 添加列
  • add_index_on_users_email - 索引
  • change_status_type_in_orders - 修改

安全

  • 始终先在开发数据库上测试
  • 在运行迁移前备份生产
  • 在支持的地方使用事务
  • 考虑非空列的数据迁移

代码审查

  • 在运行前审查生成的SQL
  • 检查回滚逻辑是否完整
  • 验证DOWN迁移中没有数据丢失
  • 测试完整的回滚周期

数据库迁移影响生产数据 - ToM验证对于此技能是强制性的 🗄️