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 从公开仓库中收录这些内容。

举报或申请下架