一键导入
database-migration
ゼロダウンタイム戦略、データ変換、ロールバック手順を使用して、ORM間およびプラットフォーム間でデータベース移行を実行します。データベースの移行、スキーマの変更、データ変換の実行、またはゼロダウンタイムデプロイメント戦略の実装時に使用します。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
ゼロダウンタイム戦略、データ変換、ロールバック手順を使用して、ORM間およびプラットフォーム間でデータベース移行を実行します。データベースの移行、スキーマの変更、データ変換の実行、またはゼロダウンタイムデプロイメント戦略の実装時に使用します。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
自動メトリクス、人間によるフィードバック、およびベンチマークを使用して、LLMアプリケーションの包括的な評価戦略を実装します。LLMのパフォーマンスをテストし、AIアプリケーションの品質を測定し、または評価フレームワークを確立する場合に使用します。
LLMのパフォーマンス、信頼性、制御性を本番環境で最大化するための高度なプロンプトエンジニアリング技術をマスターします。プロンプトの最適化、LLM出力の改善、または本番環境プロンプトテンプレートの設計時に使用します。
建設的なフィードバックを提供し、早期にバグを発見し、チームの士気を維持しながら知識共有を促進する効果的なコードレビュー実践をマスター。プルリクエストのレビュー、レビュー基準の確立、開発者のメンタリング時に使用。
体系的なデバッグ技術、プロファイリングツール、根本原因分析をマスターし、あらゆるコードベースや技術スタックでバグを効率的に追跡。バグ調査、パフォーマンス問題、予期しない動作の調査時に使用。
PlaywrightとCypressを使用したエンドツーエンドテストをマスターし、バグを捕捉し、信頼性を向上させ、高速デプロイメントを可能にする信頼性の高いテストスイートを構築。E2Eテストの実装、不安定なテストのデバッグ、テスト基準の確立時に使用。
rebase、cherry-pick、bisect、worktree、reflogを含む高度なGitワークフローをマスターし、クリーンな履歴を維持し、あらゆる状況から回復。複雑なGit履歴の管理、フィーチャーブランチでの協働、リポジトリ問題のトラブルシューティング時に使用。
| name | database-migration |
| description | ゼロダウンタイム戦略、データ変換、ロールバック手順を使用して、ORM間およびプラットフォーム間でデータベース移行を実行します。データベースの移行、スキーマの変更、データ変換の実行、またはゼロダウンタイムデプロイメント戦略の実装時に使用します。 |
English | 日本語
Sequelize、TypeORM、Prismaなどのデータベーススキーマとデータ移行、ロールバック戦略、ゼロダウンタイムデプロイメントをマスターします。
// migrations/20231201-create-users.js
module.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');
}
};
// 実行: npx sequelize-cli db:migrate
// ロールバック: npx sequelize-cli db:migrate:undo
// migrations/1701234567-CreateUsers.ts
import { 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');
}
}
// 実行: npm run typeorm migration:run
// ロールバック: npm run typeorm migration:revert
// schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique
createdAt DateTime @default(now())
}
// 移行生成: npx prisma migrate dev --name create_users
// 適用: npx prisma migrate deploy
// 安全な移行: デフォルト値でカラムを追加
module.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');
}
};
// ステップ1: 新しいカラムを追加
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.addColumn('users', 'full_name', {
type: Sequelize.STRING
});
// 古いカラムからデータをコピー
await queryInterface.sequelize.query(
'UPDATE users SET full_name = name'
);
},
down: async (queryInterface) => {
await queryInterface.removeColumn('users', 'full_name');
}
};
// ステップ2: 新しいカラムを使用するようにアプリケーションを更新
// ステップ3: 古いカラムを削除
module.exports = {
up: async (queryInterface) => {
await queryInterface.removeColumn('users', 'name');
},
down: async (queryInterface, Sequelize) => {
await queryInterface.addColumn('users', 'name', {
type: Sequelize.STRING
});
}
};
module.exports = {
up: async (queryInterface, Sequelize) => {
// 大きなテーブルの場合、複数ステップアプローチを使用
// 1. 新しいカラムを追加
await queryInterface.addColumn('users', 'age_new', {
type: Sequelize.INTEGER
});
// 2. データをコピーして変換
await queryInterface.sequelize.query(`
UPDATE users
SET age_new = CAST(age AS INTEGER)
WHERE age IS NOT NULL
`);
// 3. 古いカラムを削除
await queryInterface.removeColumn('users', 'age');
// 4. 新しいカラムをリネーム
await queryInterface.renameColumn('users', 'age_new', 'age');
},
down: async (queryInterface, Sequelize) => {
await queryInterface.changeColumn('users', 'age', {
type: Sequelize.STRING
});
}
};
module.exports = {
up: async (queryInterface, Sequelize) => {
// すべてのレコードを取得
const [users] = await queryInterface.sequelize.query(
'SELECT id, address_string FROM users'
);
// 各レコードを変換
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()
}
}
);
}
// 古いカラムを削除
await queryInterface.removeColumn('users', 'address_string');
},
down: async (queryInterface, Sequelize) => {
// 元のカラムを再構築
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');
}
};
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');
}
};
module.exports = {
up: async (queryInterface, Sequelize) => {
// バックアップテーブルを作成
await queryInterface.sequelize.query(
'CREATE TABLE users_backup AS SELECT * FROM users'
);
try {
// 移行を実行
await queryInterface.addColumn('users', 'new_field', {
type: Sequelize.STRING
});
// 移行を検証
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');
}
// バックアップを削除
await queryInterface.dropTable('users_backup');
} catch (error) {
// バックアップから復元
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;
}
}
};
// フェーズ1: 変更を後方互換にする
module.exports = {
up: async (queryInterface, Sequelize) => {
// 新しいカラムを追加(古いコードと新しいコードの両方が動作可能)
await queryInterface.addColumn('users', 'email_new', {
type: Sequelize.STRING
});
}
};
// フェーズ2: 両方のカラムに書き込むコードをデプロイ
// フェーズ3: データをバックフィル
module.exports = {
up: async (queryInterface) => {
await queryInterface.sequelize.query(`
UPDATE users
SET email_new = email
WHERE email_new IS NULL
`);
}
};
// フェーズ4: 新しいカラムから読み取るコードをデプロイ
// フェーズ5: 古いカラムを削除
module.exports = {
up: async (queryInterface) => {
await queryInterface.removeColumn('users', 'email');
}
};
// 違いを処理
module.exports = {
up: async (queryInterface, Sequelize) => {
const dialectName = queryInterface.sequelize.getDialect();
if (dialectName === 'mysql') {
await queryInterface.createTable('users', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
data: {
type: Sequelize.JSON // MySQL JSONタイプ
}
});
} else if (dialectName === 'postgres') {
await queryInterface.createTable('users', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
data: {
type: Sequelize.JSONB // PostgreSQL JSONBタイプ
}
});
}
}
};