sql-migrations
PrismaやDrizzleなど多様なツールに対応し、データベースのスキーマ変更や移行、データ操作に関するあらゆるタスクを効率的に実行するSkill。
📜 元の英語説明(参考)
Database migration mastery with Prisma, Drizzle, Knex, TypeORM, Alembic, Flyway, and golang-migrate. Use when user asks to "create a migration", "update database schema", "add a column", "remove a column", "rename a table", "set up Prisma", "rollback migration", "write SQL migration", "set up Drizzle", "zero-downtime migration", "backfill data", "squash migrations", "seed database", "migrate production", or any database schema change tasks.
🇯🇵 日本人クリエイター向け解説
PrismaやDrizzleなど多様なツールに対応し、データベースのスキーマ変更や移行、データ操作に関するあらゆるタスクを効率的に実行するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o sql-migrations.zip https://jpskill.com/download/6127.zip && unzip -o sql-migrations.zip && rm sql-migrations.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/6127.zip -OutFile "$d\sql-migrations.zip"; Expand-Archive "$d\sql-migrations.zip" -DestinationPath $d -Force; ri "$d\sql-migrations.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
sql-migrations.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
sql-migrationsフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-17
- 取得日時
- 2026-05-17
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
SQLマイグレーション
マイグレーションの基礎
マイグレーションとは、データベーススキーマに対するバージョン管理された増分変更のことです。マイグレーションは順序通りに実行され、メタデータテーブル(例: schema_migrations、_prisma_migrations)を介して、どのマイグレーションが適用されたかを追跡します。
Up/Down: アップマイグレーションは変更を適用します。ダウンマイグレーションはそれを元に戻します。すべての変更が元に戻せるわけではありません(データのある列を削除するとデータが失われます)。
バージョン管理 vs 繰り返し可能: バージョン管理されたマイグレーションは、順序通りに一度だけ実行されます(001、002、...)。繰り返し可能なマイグレーション(Flywayの R__ プレフィックス)は、チェックサムが変更されるたびに再実行されます。これはビュー、関数、ストアドプロシージャに役立ちます。
冪等なマイグレーション: IF NOT EXISTS / IF EXISTS ガードを使用すると、マイグレーションが既に適用された状態に対してエラーを発生させることなく、安全に再実行できます。
CREATE TABLE IF NOT EXISTS users (...);
ALTER TABLE users ADD COLUMN IF NOT EXISTS role TEXT;
DROP INDEX IF EXISTS idx_users_email;
ツール固有のパターン
Prisma
npm install prisma @prisma/client
npx prisma init
コマンド:
npx prisma migrate dev --name add_users_table # マイグレーションの作成 + 適用 (開発環境)
npx prisma migrate deploy # 保留中のマイグレーションを適用 (本番環境)
npx prisma migrate reset # 削除 + 再作成 + シード (破壊的)
npx prisma migrate status # マイグレーションの状態を確認
npx prisma generate # クライアントを再生成
npx prisma db push # マイグレーションファイルなしでスキーマをプッシュ (プロトタイプ作成)
npx prisma db seed # シードスクリプトを実行
npx prisma studio # データベースGUIを開く
Drizzle
npm install drizzle-orm drizzle-kit
コマンド:
npx drizzle-kit generate # スキーマの差分からマイグレーションを生成
npx drizzle-kit migrate # マイグレーションを適用
npx drizzle-kit push # スキーマを直接プッシュ (プロトタイプ作成)
npx drizzle-kit studio # Drizzle Studioを開く
npx drizzle-kit drop # マイグレーションを削除
Knex
npm install knex pg
npx knex init # knexfile.jsを作成
npx knex migrate:make add_users_table # マイグレーションを作成
npx knex migrate:latest # 保留中のものを実行
npx knex migrate:rollback # 最後のバッチを元に戻す
npx knex migrate:rollback --all # すべてを元に戻す
npx knex seed:make seed_users # シードファイルを作成
npx knex seed:run # シードを実行
TypeORM
npx typeorm migration:create src/migrations/AddUsersTable
npx typeorm migration:generate -d src/data-source.ts src/migrations/AddUsersTable
npx typeorm migration:run -d src/data-source.ts
npx typeorm migration:revert -d src/data-source.ts
Alembic (Python / SQLAlchemy)
alembic init alembic # 初期化
alembic revision --autogenerate -m "add users table"
alembic upgrade head # すべてを適用
alembic downgrade -1 # 最後を元に戻す
alembic history # マイグレーションを一覧表示
alembic current # 現在のリビジョンを表示
Flyway (Java / JVM)
flyway migrate # 保留中のものを適用
flyway info # 状態を表示
flyway validate # 適用されたものがローカルと一致するか検証
flyway repair # メタデータテーブルを修正
flyway clean # すべてのオブジェクトを削除 (破壊的)
# 命名規則: V1__Create_users.sql, V2__Add_email_index.sql
# 繰り返し可能: R__Create_views.sql (チェックサムが変更されると再実行される)
golang-migrate
migrate create -ext sql -dir db/migrations -seq add_users_table
migrate -path db/migrations -database "$DB_URL" up
migrate -path db/migrations -database "$DB_URL" down 1
migrate -path db/migrations -database "$DB_URL" force 3 # ダーティな状態を修正
安全なマイグレーションの記述 (ゼロダウンタイム)
列の追加
既存の行があるテーブルに、デフォルト値のない NOT NULL 列を追加してはいけません。安全な手順は次のとおりです。
- 列をNULL許容として追加します:
ALTER TABLE users ADD COLUMN role TEXT; - 新しい列を書き込むコードをデプロイします。
- 既存の行をバックフィルします:
UPDATE users SET role = 'user' WHERE role IS NULL; - 制約を追加します:
ALTER TABLE users ALTER COLUMN role SET NOT NULL;
列の削除
コードがまだ読み込んでいる列を削除してはいけません。安全な手順は次のとおりです。
- アプリケーションコードで列の読み込みを停止します。デプロイします。
- 列への書き込みを停止します。デプロイします。
- 列を削除します:
ALTER TABLE users DROP COLUMN legacy_field;
列またはテーブルの名前変更
名前変更は既存のクエリを即座に壊します。安全な手順は次のとおりです。
- 新しい列を追加します。古い列と新しい列の両方に書き込むコードをデプロイします。
- 古い列から新しい列にバックフィルします。
- 読み込みを新しい列に切り替えます。デプロイします。
- 古い列への書き込みを停止します。デプロイします。
- 古い列を削除します。
テーブルの場合も、同じ拡張-移行-縮小パターンが適用されます。あるいは、移行中に古い名前でビューを作成することもできます。
インデックスの作成
Postgresでは、CREATE INDEX はテーブルを書き込みのためにロックします。CONCURRENTLY を使用してください。
-- 安全: 書き込みをブロックしません (Postgresのみ、トランザクション内では実行できません)
CREATE INDEX CONCURRENTLY idx_users_email ON users(email);
-- 安全に削除もできます
DROP INDEX CONCURRENTLY IF EXISTS idx_users_email;
各ファイルをトランザクションでラップするマイグレーションツールでは、その特定のマイグレーションのトランザクションを無効にするか、インデックス作成を別途実行する必要があります。
制約の追加
-- ロックせずに外部キーを追加 (Postgres)
ALTER TABLE posts ADD CONSTRAINT fk_posts_author
FOREIGN KEY (author_id) REFERENCES users(id) NOT VALID;
ALTER TABLE posts VALIDATE CONSTRAINT fk_posts_author;
-- ロックせずにチェック制約を追加 (Postgres 12+)
ALTER TABLE users ADD CONSTRAINT chk_role
CHECK (role IN ('admin', 'user', 'moderator')) NOT VALID;
ALTER TABLE users VALIDATE CONSTRAINT chk_role;
データマイグレーション vs スキーママグレーション
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
SQL Migrations
Migration Fundamentals
A migration is a versioned, incremental change to a database schema. Migrations run in order and track which have been applied via a metadata table (e.g., schema_migrations, _prisma_migrations).
Up/Down: The up migration applies the change. The down migration reverses it. Not all changes are reversible (dropping a column with data destroys it).
Versioned vs Repeatable: Versioned migrations run once in order (001, 002, ...). Repeatable migrations (Flyway R__ prefix) re-run whenever their checksum changes -- useful for views, functions, and stored procedures.
Idempotent migrations: Use IF NOT EXISTS / IF EXISTS guards so a migration can be re-run safely without erroring on already-applied state:
CREATE TABLE IF NOT EXISTS users (...);
ALTER TABLE users ADD COLUMN IF NOT EXISTS role TEXT;
DROP INDEX IF EXISTS idx_users_email;
Tool-Specific Patterns
Prisma
npm install prisma @prisma/client
npx prisma init
Commands:
npx prisma migrate dev --name add_users_table # create + apply migration (dev)
npx prisma migrate deploy # apply pending migrations (production)
npx prisma migrate reset # drop + recreate + seed (destructive)
npx prisma migrate status # check migration status
npx prisma generate # regenerate client
npx prisma db push # push schema without migration file (prototyping)
npx prisma db seed # run seed script
npx prisma studio # open database GUI
Drizzle
npm install drizzle-orm drizzle-kit
Commands:
npx drizzle-kit generate # generate migration from schema diff
npx drizzle-kit migrate # apply migrations
npx drizzle-kit push # push schema directly (prototyping)
npx drizzle-kit studio # open Drizzle Studio
npx drizzle-kit drop # drop a migration
Knex
npm install knex pg
npx knex init # create knexfile.js
npx knex migrate:make add_users_table # create migration
npx knex migrate:latest # run pending
npx knex migrate:rollback # undo last batch
npx knex migrate:rollback --all # undo everything
npx knex seed:make seed_users # create seed file
npx knex seed:run # run seeds
TypeORM
npx typeorm migration:create src/migrations/AddUsersTable
npx typeorm migration:generate -d src/data-source.ts src/migrations/AddUsersTable
npx typeorm migration:run -d src/data-source.ts
npx typeorm migration:revert -d src/data-source.ts
Alembic (Python / SQLAlchemy)
alembic init alembic # initialize
alembic revision --autogenerate -m "add users table"
alembic upgrade head # apply all
alembic downgrade -1 # undo last
alembic history # list migrations
alembic current # show current revision
Flyway (Java / JVM)
flyway migrate # apply pending
flyway info # show status
flyway validate # verify applied match local
flyway repair # fix metadata table
flyway clean # drop all objects (destructive)
# Naming: V1__Create_users.sql, V2__Add_email_index.sql
# Repeatable: R__Create_views.sql (re-runs when checksum changes)
golang-migrate
migrate create -ext sql -dir db/migrations -seq add_users_table
migrate -path db/migrations -database "$DB_URL" up
migrate -path db/migrations -database "$DB_URL" down 1
migrate -path db/migrations -database "$DB_URL" force 3 # fix dirty state
Writing Safe Migrations (Zero-Downtime)
Adding a Column
Never add a NOT NULL column without a default to a table that has existing rows. The safe sequence:
- Add column as nullable:
ALTER TABLE users ADD COLUMN role TEXT; - Deploy code that writes the new column.
- Backfill existing rows:
UPDATE users SET role = 'user' WHERE role IS NULL; - Add the constraint:
ALTER TABLE users ALTER COLUMN role SET NOT NULL;
Removing a Column
Never drop a column that code still reads. The safe sequence:
- Stop reading the column in application code. Deploy.
- Stop writing the column. Deploy.
- Drop the column:
ALTER TABLE users DROP COLUMN legacy_field;
Renaming a Column or Table
Renaming breaks existing queries instantly. The safe sequence:
- Add the new column. Deploy code that writes to both old and new.
- Backfill new column from old column.
- Switch reads to new column. Deploy.
- Stop writing old column. Deploy.
- Drop old column.
For tables, the same expand-migrate-contract pattern applies. Alternatively, create a view with the old name during transition.
Index Creation
On Postgres, CREATE INDEX locks the table for writes. Use CONCURRENTLY:
-- Safe: does not block writes (Postgres only, cannot run inside a transaction)
CREATE INDEX CONCURRENTLY idx_users_email ON users(email);
-- Drop safely too
DROP INDEX CONCURRENTLY IF EXISTS idx_users_email;
In migration tools that wrap each file in a transaction, you must disable the transaction for that specific migration or run the index creation separately.
Adding Constraints
-- Add foreign key without locking (Postgres)
ALTER TABLE posts ADD CONSTRAINT fk_posts_author
FOREIGN KEY (author_id) REFERENCES users(id) NOT VALID;
ALTER TABLE posts VALIDATE CONSTRAINT fk_posts_author;
-- Add check constraint without locking (Postgres 12+)
ALTER TABLE users ADD CONSTRAINT chk_role
CHECK (role IN ('admin', 'user', 'moderator')) NOT VALID;
ALTER TABLE users VALIDATE CONSTRAINT chk_role;
Data Migrations vs Schema Migrations
Keep them separate. Schema migrations change structure (DDL). Data migrations change content (DML). Mixing them causes problems:
- Schema migrations should be fast and reversible. Data migrations on large tables are slow.
- Schema rollbacks cannot un-delete data.
- Data migrations may need batching; schema migrations do not.
-- Schema migration: 005_add_status_column.sql
ALTER TABLE orders ADD COLUMN status TEXT;
-- Data migration: 006_backfill_status.sql (separate file)
UPDATE orders SET status = 'completed' WHERE completed_at IS NOT NULL;
UPDATE orders SET status = 'pending' WHERE completed_at IS NULL;
Large Table Migrations
For tables with millions of rows, a single ALTER TABLE or UPDATE can lock the table or run for hours.
Batched updates: Process rows in chunks to avoid long locks and transaction log bloat:
-- Backfill in batches of 10,000
DO $$
DECLARE batch_size INT := 10000;
BEGIN
LOOP
UPDATE orders SET status = 'pending'
WHERE id IN (SELECT id FROM orders WHERE status IS NULL LIMIT batch_size);
EXIT WHEN NOT FOUND;
COMMIT;
END LOOP;
END $$;
Online schema change tools (MySQL): pt-online-schema-change (Percona) and gh-ost (GitHub) create a shadow table, copy data, replay binlog changes, then swap. Use these for any DDL on large MySQL tables in production.
# pt-online-schema-change
pt-online-schema-change --alter "ADD COLUMN status VARCHAR(50)" \
--execute D=mydb,t=orders
# gh-ost
gh-ost --alter "ADD COLUMN status VARCHAR(50)" \
--database=mydb --table=orders --execute
Squashing / Consolidating Migrations
When migration count grows unwieldy (100+ files), squash them:
- Dump the current schema:
pg_dump --schema-only > baseline.sql - Delete all existing migration files.
- Create a single baseline migration from the dump.
- Mark it as applied in the migrations table without running it.
- All future migrations build from this baseline.
Prisma: npx prisma migrate diff can generate a diff between two states. Drizzle and Knex do not have built-in squash -- do it manually.
Rollback Strategies and Limitations
Always write down migrations but understand their limits:
- Dropping a column is irreversible (data is gone). The down migration can recreate the column but not the data.
- Data migrations cannot be meaningfully reversed if the old value was overwritten.
- Rollbacks in production are risky. Prefer forward-fixing: deploy a new migration that undoes the change.
-- Down migration: 003_add_role.down.sql
ALTER TABLE users DROP COLUMN IF EXISTS role;
Migration Locking and Concurrent Deploys
Most migration tools use advisory locks to prevent two processes from running migrations simultaneously. If your deployment runs multiple instances:
- Prisma and Flyway acquire locks automatically.
- Knex, golang-migrate: only one instance should run migrations (use a deploy step, not application startup).
- If a migration crashes mid-run and leaves a lock, you may need to manually clear the lock or use
migrate force(golang-migrate) /flyway repair.
Run migrations in a dedicated CI/CD step, not at application boot.
Testing Migrations
- Test against a production-like dataset, not an empty database. Schema changes that work on empty tables may lock or fail on tables with millions of rows.
- Run
upthendownthenupagain to verify reversibility. - Use a copy of production data (anonymized) in staging.
- Check migration speed: if a migration takes > 1 second on staging, it will take longer in production. Plan accordingly.
Seeding Data
Seeds populate the database with initial or test data. Keep seeds idempotent.
-- Idempotent seed
INSERT INTO roles (name) VALUES ('admin'), ('user'), ('moderator')
ON CONFLICT (name) DO NOTHING;
// Prisma seed (prisma/seed.ts, configured in package.json "prisma.seed")
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
async function main() {
await prisma.role.upsert({
where: { name: "admin" },
update: {},
create: { name: "admin" },
});
}
main().finally(() => prisma.$disconnect());
Environment-Specific Migrations
- Dev: Use
migrate reset/db pushfreely. Speed matters more than safety. - Staging: Mirror production. Run the exact same migration files. Test with realistic data volumes.
- Production: Never use
reset,push, orclean. Onlymigrate deploy/migrate up. Always back up before migrating.
Use environment variables to control connection strings. Never hardcode credentials in migration files.
Migration CI/CD Integration
# GitHub Actions example
- name: Run migrations
run: npx prisma migrate deploy
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
# Validate migrations in PR checks
- name: Check migration status
run: |
npx prisma migrate status
npx prisma migrate diff --from-migrations ./prisma/migrations --to-schema-datamodel ./prisma/schema.prisma --exit-code
CI pipeline checklist:
- Run migrations against a test database before merging.
- Verify no pending migrations exist after running.
- Run the application test suite after migrations.
- In production deploys, run migrations before deploying new application code (if the migration is backward-compatible) or after (if old code must stop using removed columns first).
Raw SQL Migration Structure
migrations/
├── 001_create_users.up.sql
├── 001_create_users.down.sql
├── 002_create_posts.up.sql
├── 002_create_posts.down.sql
└── 003_add_email_index.up.sql
-- Example up migration
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(255),
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Example down migration
DROP TABLE IF EXISTS users;
Quick Reference
1. One change per migration -- easier to review, rollback, and debug
2. Always write down migrations for reversibility
3. Never edit an applied migration -- create a new one
4. Test migrations against production-like data
5. Wrap multi-statement migrations in transactions (except CONCURRENTLY)
6. Separate schema migrations from data migrations
7. Backfill data in a separate migration from the schema change
8. Run migrations in CI/CD, not at application boot
9. Back up the database before running production migrations