D1 Migration

jezweb/claude-skills/archive/plugins/cloudflare/skills/d1-migration

作者 jezweb64965d9d9fc7無授權條款1K 個星標收錄於 2026年10月8日更新於 2026年10月8日儲存庫3 天前更新

Cloudflare D1 migration workflow: generate with Drizzle, inspect SQL for gotchas, apply to local and remote, fix stuck migrations, handle partial failures. Use when running migrations, fixing migration errors, or setting up D1 schemas.

AI 產生的概覽

使用 Drizzle ORM 進行 Cloudflare D1 資料庫遷移的引導式工作流程,涵蓋產生、檢查、套用與修復。

功能
此技能提供使用 Drizzle ORM 產生的 Cloudflare D1 遷移的分步操作流程。它說明如何產生遷移 SQL、檢查其中具破壞性的資料表重建模式、將遷移同時套用到本機與遠端資料庫,並以 PRAGMA 查詢驗證結果。它也涵蓋診斷並手動記錄卡住或部分套用的遷移、分批大量插入以避開 D1 參數上限,以及為新專案設定 D1 資料庫。
適用情境
適用於執行 D1 遷移、遷移發生錯誤或看似卡住,以及為新專案設定 D1 schema 的情境。產生的 Drizzle SQL 在套用前需要審查時也適用。
執行需求
需要一個使用 Drizzle ORM 的 Cloudflare D1 專案、wrangler CLI,以及 db:generate、db:migrate 等套件指令碼。遠端遷移需要網路存取與 Cloudflare 憑證。不附指令碼,僅為操作說明。

D1 Migration Workflow

Guided workflow for Cloudflare D1 database migrations using Drizzle ORM.

Standard Migration Flow

1. Generate Migration

bash
pnpm db:generate

This creates a new .sql file in drizzle/ (or your configured migrations directory).

2. Inspect the SQL (CRITICAL)

Always read the generated SQL before applying. Drizzle sometimes generates destructive migrations for simple schema changes.

Red Flag: Table Recreation

If you see this pattern, the migration will likely fail:

sql
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`;

Cause: Changing a column's default value in Drizzle schema triggers full table recreation. The INSERT SELECT references the new column from the old table.

Fix: If you're only adding new columns (no type/constraint changes on existing columns), simplify to:

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

Edit the .sql file directly before applying.

3. Apply to Local

bash
pnpm db:migrate:local# or: npx wrangler d1 migrations apply DB_NAME --local

4. Apply to Remote

bash
pnpm db:migrate:remote# or: npx wrangler d1 migrations apply DB_NAME --remote

Always apply to BOTH local and remote before testing. Local-only migrations cause confusing "works locally, breaks in production" issues.

5. Verify

bash
# Check localnpx wrangler d1 execute DB_NAME --local --command "PRAGMA table_info(my_table)"
# Check remotenpx wrangler d1 execute DB_NAME --remote --command "PRAGMA table_info(my_table)"

Fixing Stuck Migrations

When a migration partially applied (e.g. column was added but migration wasn't recorded), wrangler retries it and fails on the duplicate column.

Symptoms: pnpm db:migrate errors on a migration that looks like it should be done. PRAGMA table_info shows the column exists.

Diagnosis

bash
# 1. Verify the column/table existsnpx wrangler d1 execute DB_NAME --remote \  --command "PRAGMA table_info(my_table)"
# 2. Check what migrations are recordednpx wrangler d1 execute DB_NAME --remote \  --command "SELECT * FROM d1_migrations ORDER BY id"

Fix

bash
# 3. Manually record the stuck migrationnpx 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 normallypnpm db:migrate

Prevention

  • CREATE TABLE IF NOT EXISTS — safe to re-run
  • ALTER TABLE ADD COLUMN — SQLite has no IF NOT EXISTS variant; check column existence first or use try/catch in application code
  • Always inspect generated SQL before applying (Step 2 above)

Bulk Insert Batching

D1's parameter limit causes silent failures with large multi-row INSERTs. Batch into chunks:

typescript
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);}

Why: D1 fails when rows x columns exceeds ~100-150 parameters.

Column Naming

ContextConventionExample
Drizzle schemacamelCasecaseNumber: text('case_number')
Raw SQL queriessnake_caseUPDATE cases SET case_number = ?
API responsesMatch SQL aliasesSELECT case_number FROM cases

New Project Setup

When creating a D1 database for a new project, follow this order:

  1. Deploy Worker first — npm run build && npx wrangler deploy
  2. Create D1 database — npx wrangler d1 create project-name-db
  3. Copy database_id to wrangler.jsonc d1_databases binding
  4. Redeploy — npx wrangler deploy
  5. Run migrations — apply to both local and remote

來源與署名

來源:jezweb/claude-skills位於archive/plugins/cloudflare/skills/d1-migration提交64965d9

授權條款: 無授權條款

內容歸原作者所有。SourceWeft 從公開儲存庫中收錄這些內容。

檢舉或申請下架