mcpField
D
d1-migration

d1-migration

github.com/jezwebデータ・データベース1.1k1.2k 回インストール3 週間前に更新
リポジトリ

d1-migration について

Drizzle ORM と Cloudflare D1 を使う開発者向けのマイグレーション手順です。SQL の確認、ローカルとリモートへの適用、検証や復旧に加え、一括挿入の分割と命名規則も扱います。

主な機能

  1. 01マイグレーション SQL の生成と確認
  2. 02ローカル・リモートへの適用
  3. 03スキーマと適用記録の検証
  4. 04停止したマイグレーションの診断と修復
  5. 05大量の挿入処理の分割

活用シーン

  1. 01生成 SQL にテーブル再作成がないか確認
  2. 02ローカルとリモートの D1 スキーマを同期
  3. 03重複カラムや未記録の移行問題を解消
  4. 04一括挿入時のパラメーター制限を回避

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jezweb/claude-skills --skill d1-migration

インストール後、Claude Code で/d1-migrationを入力して読み込まれたか確認します。

詳細

D1 マイグレーションのワークフロー

Drizzle ORM を使用した Cloudflare D1 データベースのマイグレーションを案内するワークフローです。

標準的なマイグレーションの流れ

1. マイグレーションを生成する
pnpm db:generate

drizzle/(または設定したマイグレーションディレクトリ)に新しい .sql ファイルが作成されます。

2. SQL を確認する(重要)

適用する前に、必ず生成された SQL を読んでください。 Drizzle は、単純なスキーマ変更でも破壊的なマイグレーションを生成することがあります。

要注意:テーブルの再作成

このパターンが見られる場合、マイグレーションは失敗する可能性が高いです。

CREATE TABLE `my_table_new` (...);
INSERT INTO `my_table_new` SELECT ..., `new_column`, ... FROM `my_table`;
--                                      ^^^ This column doesn't exist in old table!
DROP TABLE `my_table`;
ALTER TABLE `my_table_new` RENAME TO `my_table`;

原因:Drizzle スキーマでカラムの default 値を変更すると、テーブル全体の再作成が発生します。INSERT SELECT が、古いテーブルに存在しない新しいカラムを参照します。

修正方法:新しいカラムを追加するだけで(既存カラムの型や制約を変更しない場合)あれば、次のようにシンプルにします。

ALTER TABLE `my_table` ADD COLUMN `new_column` TEXT DEFAULT 'value';

適用する前に .sql ファイルを直接編集してください。

3. ローカルに適用する
pnpm db:migrate:local
# or: npx wrangler d1 migrations apply DB_NAME --local
4. リモートに適用する
pnpm db:migrate:remote
# or: npx wrangler d1 migrations apply DB_NAME --remote

テストする前に、必ずローカルとリモートの両方に適用してください。 ローカルのみにマイグレーションを適用すると、「ローカルでは動くが、本番環境では壊れる」という分かりにくい問題が発生します。

5. 検証する
# Check local
npx wrangler d1 execute DB_NAME --local --command "PRAGMA table_info(my_table)"

# Check remote
npx wrangler d1 execute DB_NAME --remote --command "PRAGMA table_info(my_table)"

停滞したマイグレーションの修正

マイグレーションが一部だけ適用された場合(例:カラムは追加されたが、マイグレーションの記録はされていない)、wrangler は再実行を試みますが、重複カラムのため失敗します。

症状:完了しているはずのマイグレーションで pnpm db:migrate がエラーになります。PRAGMA table_info ではカラムが存在することが確認できます。

診断
# 1. Verify the column/table exists
npx wrangler d1 execute DB_NAME --remote \
  --command "PRAGMA table_info(my_table)"

# 2. Check what migrations are recorded
npx wrangler d1 execute DB_NAME --remote \
  --command "SELECT * FROM d1_migrations ORDER BY id"
修正
# 3. Manually record the stuck migration
npx wrangler d1 execute DB_NAME --remote \
  --command "INSERT INTO d1_migrations (name, applied_at) VALUES ('0013_my_migration.sql', datetime('now'))"

# 4. Run remaining migrations normally
pnpm db:migrate
予防
  • CREATE TABLE IF NOT EXISTS — 再実行しても安全です
  • ALTER TABLE ADD COLUMN — SQLite には IF NOT EXISTS を指定する形式がありません。先にカラムの存在を確認するか、アプリケーションコードで try/catch を使用してください
  • 適用する前に、必ず生成された SQL を確認してください(上記のステップ 2)

一括 INSERT の分割

D1 のパラメーター数の上限により、大量の複数行 INSERT がサイレントに失敗します。チャンクに分割してください。

const BATCH_SIZE = 10;
for (let i = 0; i < allRows.length; i += BATCH_SIZE) {
  const batch = allRows.slice(i, i + BATCH_SIZE);
  await db.insert(myTable).values(batch);
}

理由:行数 × カラム数が約 100~150 個のパラメーターを超えると、D1 は失敗します。

カラムの命名規則

コンテキスト規則例
Drizzle スキーマcamelCasecaseNumber: text('case_number')
生の SQL クエリsnake_caseUPDATE cases SET case_number = ?
API レスポンスSQL のエイリアスに合わせるSELECT case_number FROM cases

新規プロジェクトのセットアップ

新しいプロジェクト用に D1 データベースを作成する場合は、次の順序で進めてください。

  1. まず Worker をデプロイする — npm run build && npx wrangler deploy
  2. D1 データベースを作成する — npx wrangler d1 create project-name-db
  3. database_id を wrangler.jsonc の d1_databases バインディングにコピーする
  4. 再デプロイする — npx wrangler deploy
  5. マイグレーションを実行する — ローカルとリモートの両方に適用する

コメント