[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-c20fe603-301a-438e-9cba-d392fec67e32":3,"$fexzuvRCQ4JgyxVEpVFpRBpLomQrLVWMfxFrEVFJaMfI":42},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":33},"c20fe603-301a-438e-9cba-d392fec67e32","database-migration","掌握ORM（Sequelize、TypeORM、Prisma）的数据库架构和数据迁移，包括回滚策略和无停机部署。","cat_coding_backend","mod_coding","sickn33,coding","---\nname: database-migration\ndescription: \"Master database schema and data migrations across ORMs (Sequelize, TypeORM, Prisma), including rollback strategies and zero-downtime deployments.\"\nrisk: unknown\nsource: community\ndate_added: \"2026-02-27\"\n---\n\n# Database Migration\n\nMaster database schema and data migrations across ORMs (Sequelize, TypeORM, Prisma), including rollback strategies and zero-downtime deployments.\n\n## Do not use this skill when\n\n- The task is unrelated to database migration\n- You need a different domain or tool outside this scope\n\n## Instructions\n\n- Clarify goals, constraints, and required inputs.\n- Apply relevant best practices and validate outcomes.\n- Provide actionable steps and verification.\n- If detailed examples are required, open `resources\u002Fimplementation-playbook.md`.\n\n## Use this skill when\n\n- Migrating between different ORMs\n- Performing schema transformations\n- Moving data between databases\n- Implementing rollback procedures\n- Zero-downtime deployments\n- Database version upgrades\n- Data model refactoring\n\n## ORM Migrations\n\n### Sequelize Migrations\n```javascript\n\u002F\u002F migrations\u002F20231201-create-users.js\nmodule.exports = {\n  up: async (queryInterface, Sequelize) => {\n    await queryInterface.createTable('users', {\n      id: {\n        type: Sequelize.INTEGER,\n        primaryKey: true,\n        autoIncrement: true\n      },\n      email: {\n        type: Sequelize.STRING,\n        unique: true,\n        allowNull: false\n      },\n      createdAt: Sequelize.DATE,\n      updatedAt: Sequelize.DATE\n    });\n  },\n\n  down: async (queryInterface, Sequelize) => {\n    await queryInterface.dropTable('users');\n  }\n};\n\n\u002F\u002F Run: npx sequelize-cli db:migrate\n\u002F\u002F Rollback: npx sequelize-cli db:migrate:undo\n```\n\n### TypeORM Migrations\n```typescript\n\u002F\u002F migrations\u002F1701234567-CreateUsers.ts\nimport { MigrationInterface, QueryRunner, Table } from 'typeorm';\n\nexport class CreateUsers1701234567 implements MigrationInterface {\n  public async up(queryRunner: QueryRunner): Promise\u003Cvoid> {\n    await queryRunner.createTable(\n      new Table({\n        name: 'users',\n        columns: [\n          {\n            name: 'id',\n            type: 'int',\n            isPrimary: true,\n            isGenerated: true,\n            generationStrategy: 'increment'\n          },\n          {\n            name: 'email',\n            type: 'varchar',\n            isUnique: true\n          },\n          {\n            name: 'created_at',\n            type: 'timestamp',\n            default: 'CURRENT_TIMESTAMP'\n          }\n        ]\n      })\n    );\n  }\n\n  public async down(queryRunner: QueryRunner): Promise\u003Cvoid> {\n    await queryRunner.dropTable('users');\n  }\n}\n\n\u002F\u002F Run: npm run typeorm migration:run\n\u002F\u002F Rollback: npm run typeorm migration:revert\n```\n\n### Prisma Migrations\n```prisma\n\u002F\u002F schema.prisma\nmodel User {\n  id        Int      @id @default(autoincrement())\n  email     String   @unique\n  createdAt DateTime @default(now())\n}\n\n\u002F\u002F Generate migration: npx prisma migrate dev --name create_users\n\u002F\u002F Apply: npx prisma migrate deploy\n```\n\n## Schema Transformations\n\n### Adding Columns with Defaults\n```javascript\n\u002F\u002F Safe migration: add column with default\nmodule.exports = {\n  up: async (queryInterface, Sequelize) => {\n    await queryInterface.addColumn('users', 'status', {\n      type: Sequelize.STRING,\n      defaultValue: 'active',\n      allowNull: false\n    });\n  },\n\n  down: async (queryInterface) => {\n    await queryInterface.removeColumn('users', 'status');\n  }\n};\n```\n\n### Renaming Columns (Zero Downtime)\n```javascript\n\u002F\u002F Step 1: Add new column\nmodule.exports = {\n  up: async (queryInterface, Sequelize) => {\n    await queryInterface.addColumn('users', 'full_name', {\n      type: Sequelize.STRING\n    });\n\n    \u002F\u002F Copy data from old column\n    await queryInterface.sequelize.query(\n      'UPDATE users SET full_name = name'\n    );\n  },\n\n  down: async (queryInterface) => {\n    await queryInterface.removeColumn('users', 'full_name');\n  }\n};\n\n\u002F\u002F Step 2: Update application to use new column\n\n\u002F\u002F Step 3: Remove old column\nmodule.exports = {\n  up: async (queryInterface) => {\n    await queryInterface.removeColumn('users', 'name');\n  },\n\n  down: async (queryInterface, Sequelize) => {\n    await queryInterface.addColumn('users', 'name', {\n      type: Sequelize.STRING\n    });\n  }\n};\n```\n\n### Changing Column Types\n```javascript\nmodule.exports = {\n  up: async (queryInterface, Sequelize) => {\n    \u002F\u002F For large tables, use multi-step approach\n\n    \u002F\u002F 1. Add new column\n    await queryInterface.addColumn('users', 'age_new', {\n      type: Sequelize.INTEGER\n    });\n\n    \u002F\u002F 2. Copy and transform data\n    await queryInterface.sequelize.query(`\n      UPDATE users\n      SET age_new = CAST(age AS INTEGER)\n      WHERE age IS NOT NULL\n    `);\n\n    \u002F\u002F 3. Drop old column\n    await queryInterface.removeColumn('users', 'age');\n\n    \u002F\u002F 4. Rename new column\n    await queryInterface.renameColumn('users', 'age_new', 'age');\n  },\n\n  down: async (queryInterface, Sequelize) => {\n    await queryInterface.changeColumn('users', 'age', {\n      type: Sequelize.STRING\n    });\n  }\n};\n```\n\n## Data Transformations\n\n### Complex Data Migration\n```javascript\nmodule.exports = {\n  up: async (queryInterface, Sequelize) => {\n    \u002F\u002F Get all records\n    const [users] = await queryInterface.sequelize.query(\n      'SELECT id, address_string FROM users'\n    );\n\n    \u002F\u002F Transform each record\n    for (const user of users) {\n      const addressParts = user.address_string.split(',');\n\n      await queryInterface.sequelize.query(\n        `UPDATE users\n         SET street = :street,\n             city = :city,\n             state = :state\n         WHERE id = :id`,\n        {\n          replacements: {\n            id: user.id,\n            street: addressParts[0]?.trim(),\n            city: addressParts[1]?.trim(),\n            state: addressParts[2]?.trim()\n          }\n        }\n      );\n    }\n\n    \u002F\u002F Drop old column\n    await queryInterface.removeColumn('users', 'address_string');\n  },\n\n  down: async (queryInterface, Sequelize) => {\n    \u002F\u002F Reconstruct original column\n    await queryInterface.addColumn('users', 'address_string', {\n      type: Sequelize.STRING\n    });\n\n    await queryInterface.sequelize.query(`\n      UPDATE users\n      SET address_string = CONCAT(street, ', ', city, ', ', state)\n    `);\n\n    await queryInterface.removeColumn('users', 'street');\n    await queryInterface.removeColumn('users', 'city');\n    await queryInterface.removeColumn('users', 'state');\n  }\n};\n```\n\n## Rollback Strategies\n\n### Transaction-Based Migrations\n```javascript\nmodule.exports = {\n  up: async (queryInterface, Sequelize) => {\n    const transaction = await queryInterface.sequelize.transaction();\n\n    try {\n      await queryInterface.addColumn(\n        'users',\n        'verified',\n        { type: Sequelize.BOOLEAN, defaultValue: false },\n        { transaction }\n      );\n\n      await queryInterface.sequelize.query(\n        'UPDATE users SET verified = true WHERE email_verified_at IS NOT NULL',\n        { transaction }\n      );\n\n      await transaction.commit();\n    } catch (error) {\n      await transaction.rollback();\n      throw error;\n    }\n  },\n\n  down: async (queryInterface) => {\n    await queryInterface.removeColumn('users', 'verified');\n  }\n};\n```\n\n### Checkpoint-Based Rollback\n```javascript\nmodule.exports = {\n  up: async (queryInterface, Sequelize) => {\n    \u002F\u002F Create backup table\n    await queryInterface.sequelize.query(\n      'CREATE TABLE users_backup AS SELECT * FROM users'\n    );\n\n    try {\n      \u002F\u002F Perform migration\n      await queryInterface.addColumn('users', 'new_field', {\n        type: Sequelize.STRING\n      });\n\n      \u002F\u002F Verify migration\n      const [result] = await queryInterface.sequelize.query(\n        \"SELECT COUNT(*) as count FROM users WHERE new_field IS NULL\"\n      );\n\n      if (result[0].count > 0) {\n        throw new Error('Migration verification failed');\n      }\n\n      \u002F\u002F Drop backup\n      await queryInterface.dropTable('users_backup');\n    } catch (error) {\n      \u002F\u002F Restore from backup\n      await queryInterface.sequelize.query('DROP TABLE users');\n      await queryInterface.sequelize.query(\n        'CREATE TABLE users AS SELECT * FROM users_backup'\n      );\n      await queryInterface.dropTable('users_backup');\n      throw error;\n    }\n  }\n};\n```\n\n## Zero-Downtime Migrations\n\n### Blue-Green Deployment Strategy\n```javascript\n\u002F\u002F Phase 1: Make changes backward compatible\nmodule.exports = {\n  up: async (queryInterface, Sequelize) => {\n    \u002F\u002F Add new column (both old and new code can work)\n    await queryInterface.addColumn('users', 'email_new', {\n      type: Sequelize.STRING\n    });\n  }\n};\n\n\u002F\u002F Phase 2: Deploy code that writes to both columns\n\n\u002F\u002F Phase 3: Backfill data\nmodule.exports = {\n  up: async (queryInterface) => {\n    await queryInterface.sequelize.query(`\n      UPDATE users\n      SET email_new = email\n      WHERE email_new IS NULL\n    `);\n  }\n};\n\n\u002F\u002F Phase 4: Deploy code that reads from new column\n\n\u002F\u002F Phase 5: Remove old column\nmodule.exports = {\n  up: async (queryInterface) => {\n    await queryInterface.removeColumn('users', 'email');\n  }\n};\n```\n\n## Cross-Database Migrations\n\n### PostgreSQL to MySQL\n```javascript\n\u002F\u002F Handle differences\nmodule.exports = {\n  up: async (queryInterface, Sequelize) => {\n    const dialectName = queryInterface.sequelize.getDialect();\n\n    if (dialectName === 'mysql') {\n      await queryInterface.createTable('users', {\n        id: {\n          type: Sequelize.INTEGER,\n          primaryKey: true,\n          autoIncrement: true\n        },\n        data: {\n          type: Sequelize.JSON  \u002F\u002F MySQL JSON type\n        }\n      });\n    } else if (dialectName === 'postgres') {\n      await queryInterface.createTable('users', {\n        id: {\n          type: Sequelize.INTEGER,\n          primaryKey: true,\n          autoIncrement: true\n        },\n        data: {\n          type: Sequelize.JSONB  \u002F\u002F PostgreSQL JSONB type\n        }\n      });\n    }\n  }\n};\n```\n\n## Resources\n\n- **references\u002Form-switching.md**: ORM migration guides\n- **references\u002Fschema-migration.md**: Schema transformation patterns\n- **references\u002Fdata-transformation.md**: Data migration scripts\n- **references\u002Frollback-strategies.md**: Rollback procedures\n- **assets\u002Fschema-migration-template.sql**: SQL migration templates\n- **assets\u002Fdata-migration-script.py**: Data migration utilities\n- **scripts\u002Ftest-migration.sh**: Migration testing script\n\n## Best Practices\n\n1. **Always Provide Rollback**: Every up() needs a down()\n2. **Test Migrations**: Test on staging first\n3. **Use Transactions**: Atomic migrations when possible\n4. **Backup First**: Always backup before migration\n5. **Small Changes**: Break into small, incremental steps\n6. **Monitor**: Watch for errors during deployment\n7. **Document**: Explain why and how\n8. **Idempotent**: Migrations should be rerunnable\n\n## Common Pitfalls\n\n- Not testing rollback procedures\n- Making breaking changes without downtime strategy\n- Forgetting to handle NULL values\n- Not considering index performance\n- Ignoring foreign key constraints\n- Migrating too much data at once\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,196,1544,"2026-05-16 13:14:17",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"编程开发","coding","mdi-code-braces","代码生成、调试、审查，提升开发效率",2,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":25,"skillCount":32,"createdAt":26},"后端开发","backend","mdi-server","API、数据库、服务端架构",296,[34],{"id":35,"skillId":4,"version":36,"fileName":37,"fileSize":38,"filePath":39,"fileHash":40,"manifest":41,"createdAt":19},"bce621d1-58be-4859-a079-b408c9f7749f","1.0.0","database-migration.zip",3357,"uploads\u002Fskills\u002Fc20fe603-301a-438e-9cba-d392fec67e32\u002Fdatabase-migration.zip","1fcf83bd8a42795198ee3e1e345d7a65aed36ba3d7775503a1b318b8082a11b9","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":11388}]",{"code":43,"message":44,"data":45},200,"success",{"items":46,"stats":47,"page":50},[],{"averageRating":48,"totalRatings":48,"ratingCounts":49},0,[48,48,48,48,48],{"limit":51,"offset":48,"hasMore":52,"nextOffset":51,"ratedOnly":16},15,false]