数据库迁移生成器
生成数据库迁移文件,包含模式变更和回滚功能,内置ToM验证以确保数据库操作安全。
何时调用
自动调用当用户提及:
- “创建迁移”
- “添加表格”
- “修改模式”
- “更改数据库”
- “数据库迁移为[变更]”
- “向[表格]添加列”
- “重命名[表格/列]”
功能描述
- 检测迁移框架(Knex, Prisma, TypeORM, 原始SQL)
- 收集迁移需求
- 在生成前验证理解(ToM检查点 - 对于数据库变更至关重要)
- 带时间戳生成迁移文件
- 创建模式变更(上迁移)
- 创建回滚(下迁移)
- 验证迁移安全性
- 显示迁移摘要
执行步骤
第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验证对于此技能是强制性的 🗄️