d1-migration by jezweb/claude-skills
npx skills add https://github.com/jezweb/claude-skills --skill d1-migration使用 Drizzle ORM 进行 Cloudflare D1 数据库迁移的指导性工作流。
pnpm db:generate
这会在 drizzle/ 目录(或你配置的迁移目录)中创建一个新的 .sql 文件。
在应用之前,务必阅读生成的 SQL。 Drizzle 有时会为简单的模式更改生成破坏性迁移。
如果你看到以下模式,迁移很可能会失败:
CREATE TABLE `my_table_new` (...);
INSERT INTO `my_table_new` SELECT ..., `new_column`, ... FROM `my_table`;
-- ^^^ 此列在旧表中不存在!
DROP TABLE `my_table`;
ALTER TABLE `my_table_new` RENAME TO `my_table`;
原因:在 Drizzle 模式中更改列的 default 值会触发完整的表重建。INSERT SELECT 语句引用了旧表中的新列。
修复:如果你只是添加新列(没有更改现有列的类型或约束),可以简化为:
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
ALTER TABLE `my_table` ADD COLUMN `new_column` TEXT DEFAULT 'value';
在应用之前直接编辑 .sql 文件。
pnpm db:migrate:local
# 或:npx wrangler d1 migrations apply DB_NAME --local
pnpm db:migrate:remote
# 或:npx wrangler d1 migrations apply DB_NAME --remote
在测试之前,务必同时应用到本地和远程环境。 仅应用到本地会导致令人困惑的“本地工作正常,生产环境出错”问题。
# 检查本地
npx wrangler d1 execute DB_NAME --local --command "PRAGMA table_info(my_table)"
# 检查远程
npx wrangler d1 execute DB_NAME --remote --command "PRAGMA table_info(my_table)"
当迁移部分应用时(例如,列已添加但迁移未被记录),wrangler 会重试该迁移,并在重复列上失败。
症状:pnpm db:migrate 在一个看起来应该已经完成的迁移上出错。PRAGMA table_info 显示该列已存在。
# 1. 验证列/表是否存在
npx wrangler d1 execute DB_NAME --remote \
--command "PRAGMA table_info(my_table)"
# 2. 检查已记录的迁移
npx wrangler d1 execute DB_NAME --remote \
--command "SELECT * FROM d1_migrations ORDER BY id"
# 3. 手动记录卡住的迁移
npx wrangler d1 execute DB_NAME --remote \
--command "INSERT INTO d1_migrations (name, applied_at) VALUES ('0013_my_migration.sql', datetime('now'))"
# 4. 正常运行剩余的迁移
pnpm db:migrate
CREATE TABLE IF NOT EXISTS — 可以安全地重新运行ALTER TABLE ADD COLUMN — SQLite 没有 IF NOT EXISTS 变体;在应用代码中先检查列是否存在或使用 try/catchD1 的参数限制会导致大型多行 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 模式 | camelCase | caseNumber: text('case_number') |
| 原始 SQL 查询 | snake_case | UPDATE cases SET case_number = ? |
| API 响应 | 匹配 SQL 别名 | SELECT case_number FROM cases |
为新项目创建 D1 数据库时,请遵循以下顺序:
npm run build && npx wrangler deploynpx wrangler d1 create project-name-dbwrangler.jsonc 的 d1_databases 绑定中npx wrangler deploy每周安装量
177
仓库
GitHub 星标数
643
首次出现
13 天前
安全审计
安装于
opencode169
kimi-cli168
gemini-cli168
amp168
cline168
github-copilot168
Guided workflow for Cloudflare D1 database migrations using Drizzle ORM.
pnpm db:generate
This creates a new .sql file in drizzle/ (or your configured migrations directory).
Always read the generated SQL before applying. Drizzle sometimes generates destructive migrations for simple schema changes.
If you see this pattern, the migration will likely fail:
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:
ALTER TABLE `my_table` ADD COLUMN `new_column` TEXT DEFAULT 'value';
Edit the .sql file directly before applying.
pnpm db:migrate:local
# or: npx wrangler d1 migrations apply DB_NAME --local
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.
# 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)"
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.
# 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 — safe to re-runALTER TABLE ADD COLUMN — SQLite has no IF NOT EXISTS variant; check column existence first or use try/catch in application codeD1's parameter limit causes silent failures with large multi-row INSERTs. Batch into chunks:
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.
| Context | Convention | Example |
|---|---|---|
| Drizzle schema | camelCase | caseNumber: text('case_number') |
| Raw SQL queries | snake_case | UPDATE cases SET case_number = ? |
| API responses | Match SQL aliases | SELECT case_number FROM cases |
When creating a D1 database for a new project, follow this order:
npm run build && npx wrangler deploynpx wrangler d1 create project-name-dbwrangler.jsonc d1_databases bindingnpx wrangler deployWeekly Installs
177
Repository
GitHub Stars
643
First Seen
13 days ago
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode169
kimi-cli168
gemini-cli168
amp168
cline168
github-copilot168
Linkup自动化:通过Rube MCP和Composio工具包实现Linkup操作自动化
1 周安装
Lemon Squeezy自动化指南:通过Rube MCP实现电商订单与订阅管理
1 周安装
LaunchDarkly自动化指南:通过Rube MCP与Composio实现功能标志管理
1 周安装
Klipfolio自动化教程:通过Rube MCP和Composio实现仪表板操作自动化
1 周安装
Keen IO自动化指南:通过Rube MCP和Composio实现数据分析自动化
1 周安装
Ignisign自动化技能 - Claude AI签名自动化集成工具,提升文档处理效率
1 周安装