Database Migration

作者 wshobson46891e7e60da无许可证收录于 2026年10月8日更新于 2026年10月8日

Execute database migrations across ORMs and platforms with zero-downtime strategies, data transformation, and rollback procedures. Use when migrating databases, changing schemas, performing data transformations, or implementing zero-downtime deployment strategies.

AI 生成的概览

指导跨 ORM 的数据库结构与数据迁移,涵盖零停机策略、数据转换与回滚。

功能
该技能提供跨 ORM(如 Sequelize、TypeORM、Prisma)执行数据库迁移的参考指南与代码模板。内容涵盖添加、重命名、修改列类型等结构变更,复杂数据转换,基于事务与基于检查点的回滚策略,以及零停机部署模式。它产出迁移代码示例与分步流程,本身不执行任何操作;更多模板位于参考文件中。
适用场景
适用于在不同 ORM 之间迁移、变更数据库结构、在数据库之间移动或转换数据、实现回滚流程,或规划零停机部署与数据库版本升级时。
运行要求
不附带脚本,仅为说明与代码示例。实际执行迁移需要数据库以及相应 ORM 工具(Sequelize、TypeORM 或 Prisma)。

Database Migration

Master database schema and data migrations across ORMs (Sequelize, TypeORM, Prisma), including rollback strategies and zero-downtime deployments.

When to Use This Skill

  • Migrating between different ORMs
  • Performing schema transformations
  • Moving data between databases
  • Implementing rollback procedures
  • Zero-downtime deployments
  • Database version upgrades
  • Data model refactoring

ORM Migrations

Sequelize Migrations

javascript
// migrations/20231201-create-users.jsmodule.exports = {  up: async (queryInterface, Sequelize) => {    await queryInterface.createTable("users", {      id: {        type: Sequelize.INTEGER,        primaryKey: true,        autoIncrement: true,      },      email: {        type: Sequelize.STRING,        unique: true,        allowNull: false,      },      createdAt: Sequelize.DATE,      updatedAt: Sequelize.DATE,    });  },
  down: async (queryInterface, Sequelize) => {    await queryInterface.dropTable("users");  },};
// Run: npx sequelize-cli db:migrate// Rollback: npx sequelize-cli db:migrate:undo

TypeORM Migrations

typescript
// migrations/1701234567-CreateUsers.tsimport { MigrationInterface, QueryRunner, Table } from "typeorm";
export class CreateUsers1701234567 implements MigrationInterface {  public async up(queryRunner: QueryRunner): Promise<void> {    await queryRunner.createTable(      new Table({        name: "users",        columns: [          {            name: "id",            type: "int",            isPrimary: true,            isGenerated: true,            generationStrategy: "increment",          },          {            name: "email",            type: "varchar",            isUnique: true,          },          {            name: "created_at",            type: "timestamp",            default: "CURRENT_TIMESTAMP",          },        ],      }),    );  }
  public async down(queryRunner: QueryRunner): Promise<void> {    await queryRunner.dropTable("users");  }}
// Run: npm run typeorm migration:run// Rollback: npm run typeorm migration:revert

Prisma Migrations

prisma
// schema.prismamodel User {  id        Int      @id @default(autoincrement())  email     String   @unique  createdAt DateTime @default(now())}
// Generate migration: npx prisma migrate dev --name create_users// Apply: npx prisma migrate deploy

Schema Transformations

Adding Columns with Defaults

javascript
// Safe migration: add column with defaultmodule.exports = {  up: async (queryInterface, Sequelize) => {    await queryInterface.addColumn("users", "status", {      type: Sequelize.STRING,      defaultValue: "active",      allowNull: false,    });  },
  down: async (queryInterface) => {    await queryInterface.removeColumn("users", "status");  },};

Renaming Columns (Zero Downtime)

javascript
// Step 1: Add new columnmodule.exports = {  up: async (queryInterface, Sequelize) => {    await queryInterface.addColumn("users", "full_name", {      type: Sequelize.STRING,    });
    // Copy data from old column    await queryInterface.sequelize.query("UPDATE users SET full_name = name");  },
  down: async (queryInterface) => {    await queryInterface.removeColumn("users", "full_name");  },};
// Step 2: Update application to use new column
// Step 3: Remove old columnmodule.exports = {  up: async (queryInterface) => {    await queryInterface.removeColumn("users", "name");  },
  down: async (queryInterface, Sequelize) => {    await queryInterface.addColumn("users", "name", {      type: Sequelize.STRING,    });  },};

Changing Column Types

javascript
module.exports = {  up: async (queryInterface, Sequelize) => {    // For large tables, use multi-step approach
    // 1. Add new column    await queryInterface.addColumn("users", "age_new", {      type: Sequelize.INTEGER,    });
    // 2. Copy and transform data    await queryInterface.sequelize.query(`      UPDATE users      SET age_new = CAST(age AS INTEGER)      WHERE age IS NOT NULL    `);
    // 3. Drop old column    await queryInterface.removeColumn("users", "age");
    // 4. Rename new column    await queryInterface.renameColumn("users", "age_new", "age");  },
  down: async (queryInterface, Sequelize) => {    await queryInterface.changeColumn("users", "age", {      type: Sequelize.STRING,    });  },};

Data Transformations

Complex Data Migration

javascript
module.exports = {  up: async (queryInterface, Sequelize) => {    // Get all records    const [users] = await queryInterface.sequelize.query(      "SELECT id, address_string FROM users",    );
    // Transform each record    for (const user of users) {      const addressParts = user.address_string.split(",");
      await queryInterface.sequelize.query(        `UPDATE users         SET street = :street,             city = :city,             state = :state         WHERE id = :id`,        {          replacements: {            id: user.id,            street: addressParts[0]?.trim(),            city: addressParts[1]?.trim(),            state: addressParts[2]?.trim(),          },        },      );    }
    // Drop old column    await queryInterface.removeColumn("users", "address_string");  },
  down: async (queryInterface, Sequelize) => {    // Reconstruct original column    await queryInterface.addColumn("users", "address_string", {      type: Sequelize.STRING,    });
    await queryInterface.sequelize.query(`      UPDATE users      SET address_string = CONCAT(street, ', ', city, ', ', state)    `);
    await queryInterface.removeColumn("users", "street");    await queryInterface.removeColumn("users", "city");    await queryInterface.removeColumn("users", "state");  },};

Rollback Strategies

Transaction-Based Migrations

javascript
module.exports = {  up: async (queryInterface, Sequelize) => {    const transaction = await queryInterface.sequelize.transaction();
    try {      await queryInterface.addColumn(        "users",        "verified",        { type: Sequelize.BOOLEAN, defaultValue: false },        { transaction },      );
      await queryInterface.sequelize.query(        "UPDATE users SET verified = true WHERE email_verified_at IS NOT NULL",        { transaction },      );
      await transaction.commit();    } catch (error) {      await transaction.rollback();      throw error;    }  },
  down: async (queryInterface) => {    await queryInterface.removeColumn("users", "verified");  },};

Checkpoint-Based Rollback

javascript
module.exports = {  up: async (queryInterface, Sequelize) => {    // Create backup table    await queryInterface.sequelize.query(      "CREATE TABLE users_backup AS SELECT * FROM users",    );
    try {      // Perform migration      await queryInterface.addColumn("users", "new_field", {        type: Sequelize.STRING,      });
      // Verify migration      const [result] = await queryInterface.sequelize.query(        "SELECT COUNT(*) as count FROM users WHERE new_field IS NULL",      );
      if (result[0].count > 0) {        throw new Error("Migration verification failed");      }
      // Drop backup      await queryInterface.dropTable("users_backup");    } catch (error) {      // Restore from backup      await queryInterface.sequelize.query("DROP TABLE users");      await queryInterface.sequelize.query(        "CREATE TABLE users AS SELECT * FROM users_backup",      );      await queryInterface.dropTable("users_backup");      throw error;    }  },};

Additional patterns and templates

More detailed templates and worked examples live in references/details.md. Read that file for the full pattern library.

来源与署名

来源:wshobson/agents位于plugins/framework-migration/skills/database-migration提交46891e7

许可证: 无许可证

内容归原作者所有。SourceWeft 从公开仓库中收录这些内容。

举报或申请下架