api-database-drizzle
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDatabase with Drizzle ORM + Neon
使用Drizzle ORM + Neon构建数据库
Quick Guide: Use Drizzle ORM for type-safe queries, Neon serverless Postgres for edge-compatible connections. Schema-first design with automatic TypeScript types. Use RQB v2 withand object-baseddefineRelations()syntax. Relational queries withwhereavoid N+1 problems. Use transactions for atomic operations..with()
<critical_requirements>
快速指南: 使用Drizzle ORM实现类型安全查询,借助Neon无服务器Postgres实现边缘兼容连接。采用Schema-first设计,自动生成TypeScript类型。使用RQB v2的和基于对象的defineRelations()语法。通过where实现关联查询,避免N+1问题。使用事务处理原子操作。.with()
<critical_requirements>
CRITICAL: Before Using This Skill
重要提示:使用本技能前须知
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,, named constants)import type
(You MUST set in Drizzle config to map camelCase JS to snake_case SQL)
casing: 'snake_case'(You MUST use parameter (NOT ) inside transaction callbacks to ensure atomicity)
txdb(You MUST use for relational queries to avoid N+1 problems - fetches all data in single SQL query)
.with()(You MUST use for RQB v2 - the old per-table syntax is deprecated)
defineRelations()relations()</critical_requirements>
Detailed Resources:
- For code examples, see examples/ folder:
- core.md - Connection setup and schema definition (always loaded)
- queries.md - Relational queries and query builder
- relations-v2.md - RQB v2 with defineRelations() (NEW)
- transactions.md - Atomic operations
- migrations.md - Drizzle Kit workflow
- seeding.md - Development data population (includes drizzle-seed)
- For decision frameworks and anti-patterns, see reference.md
Auto-detection: drizzle-orm, @neondatabase/serverless, neon-http, db.query, db.transaction, drizzle-kit, pgTable, defineRelations, drizzle-seed
When to use:
- Serverless functions needing type-safe database queries
- Schema-first development with migrations
- Building server-rendered apps with API routes
When NOT to use:
- Simple apps using framework server actions directly (overhead not justified)
- Apps needing traditional TCP connection pooling only (use standard Postgres clients)
- Non-TypeScript projects (lose primary benefit of type safety)
- Edge functions requiring WebSocket connections (not supported in edge runtime)
<patterns>
所有代码必须遵循CLAUDE.md中的项目规范(短横线命名法、命名导出、导入顺序、、命名常量)import type
(必须在Drizzle配置中设置,以将驼峰式JS字段映射为下划线式SQL字段)
casing: 'snake_case'(事务回调中必须使用参数(而非),以确保原子性)
txdb(关联查询必须使用,避免N+1问题——单次SQL查询获取所有数据)
.with()(RQB v2必须使用——旧的单表语法已废弃)
defineRelations()relations()</critical_requirements>
详细资源:
- 代码示例请查看examples/文件夹:
- core.md - 连接配置与Schema定义(默认加载)
- queries.md - 关联查询与查询构建器
- relations-v2.md - 使用defineRelations()的RQB v2(新版)
- transactions.md - 原子操作
- migrations.md - Drizzle Kit工作流
- seeding.md - 开发数据填充(包含drizzle-seed)
- 决策框架与反模式请查看reference.md
自动检测标识: drizzle-orm, @neondatabase/serverless, neon-http, db.query, db.transaction, drizzle-kit, pgTable, defineRelations, drizzle-seed
适用场景:
- 需要类型安全数据库查询的无服务器函数
- 带迁移的Schema-first开发
- 构建带API路由的服务端渲染应用
不适用场景:
- 直接使用框架服务端操作的简单应用(开销得不偿失)
- 仅需传统TCP连接池的应用(使用标准Postgres客户端)
- 非TypeScript项目(失去类型安全核心优势)
- 需要WebSocket连接的边缘函数(边缘运行时不支持)
<patterns>
Core Patterns
核心模式
Pattern 1: Database Connection (Neon HTTP)
模式1:数据库连接(Neon HTTP)
Configure Drizzle with Neon for serverless/edge compatibility. Key setup requirements:
typescript
export const db = drizzle(sql, {
schema,
casing: "snake_case", // Maps camelCase JS to snake_case SQL
});- Validate before use (throw on missing)
DATABASE_URL - Always set to prevent field name mismatches
casing: "snake_case" - Use for HTTP (edge-compatible) or
neon()for WebSocket (long queries)Pool
Full connection setup, WebSocket config, and Drizzle Kit config in examples/core.md.
配置Drizzle与Neon,实现无服务器/边缘环境兼容。关键配置要求:
typescript
export const db = drizzle(sql, {
schema,
casing: "snake_case", // 将驼峰式JS字段映射为下划线式SQL字段
});- 使用前验证(缺失时抛出错误)
DATABASE_URL - 必须设置,避免字段名称不匹配
casing: "snake_case" - HTTP连接(边缘兼容)使用,长查询WebSocket连接使用
neon()Pool
完整连接配置、WebSocket配置与Drizzle Kit配置请查看examples/core.md。
Pattern 2: Schema Definition
模式2:Schema定义
Define tables with TypeScript types using Drizzle's schema builder:
typescript
export const companies = pgTable("companies", {
id: uuid("id").primaryKey().defaultRandom(),
name: varchar("name", { length: 255 }).notNull(),
slug: varchar("slug", { length: 255 }).unique(),
deletedAt: timestamp("deleted_at"), // Soft delete
createdAt: timestamp("created_at").defaultNow(),
});- Use for constrained values instead of varchar
pgEnum() - Always include /
createdAttimestampsupdatedAt - Add for soft deletes
deletedAt - Set on foreign keys to prevent orphaned records
onDelete: "cascade" - Use or
uuid().defaultRandom()for primary keysinteger().generatedAlwaysAsIdentity()
Full schema examples (enums, relations, junction tables, identity columns) in examples/core.md.
使用Drizzle的Schema构建器,通过TypeScript类型定义表结构:
typescript
export const companies = pgTable("companies", {
id: uuid("id").primaryKey().defaultRandom(),
name: varchar("name", { length: 255 }).notNull(),
slug: varchar("slug", { length: 255 }).unique(),
deletedAt: timestamp("deleted_at"), // 软删除
createdAt: timestamp("created_at").defaultNow(),
});- 受限值使用而非varchar
pgEnum() - 始终包含/
createdAt时间戳updatedAt - 添加实现软删除
deletedAt - 外键设置,避免孤立记录
onDelete: "cascade" - 主键使用或
uuid().defaultRandom()integer().generatedAlwaysAsIdentity()
完整Schema示例(枚举、关联、连接表、自增列)请查看examples/core.md。
Pattern 3: Relational Queries with .with()
.with()模式3:使用.with()
实现关联查询
.with()Fetch related data efficiently in a single SQL query using :
.with()typescript
const job = await db.query.jobs.findFirst({
where: and(eq(jobs.id, jobId), isNull(jobs.deletedAt)),
with: {
company: { with: { locations: true } },
jobSkills: { with: { skill: true } },
},
});
// Result is fully typed: job.company.name, job.jobSkills[0].skill.name- Use with
db.querywhen fetching related data -- single SQL query, no N+1.with() - Use query builder () for custom column selection, complex JOINs, aggregations
db.select() - Always include in WHERE conditions for soft-deleted tables
isNull(deletedAt)
Full relational query examples, N+1 anti-patterns, and dynamic filtering in examples/queries.md.
</patterns>
通过在单次SQL查询中高效获取关联数据:
.with()typescript
const job = await db.query.jobs.findFirst({
where: and(eq(jobs.id, jobId), isNull(jobs.deletedAt)),
with: {
company: { with: { locations: true } },
jobSkills: { with: { skill: true } },
},
});
// 返回结果完全类型化:job.company.name, job.jobSkills[0].skill.name- 获取关联数据时使用配合
db.query——单次SQL查询,无N+1问题.with() - 自定义列选择、复杂JOIN、聚合操作使用查询构建器()
db.select() - 软删除表的WHERE条件中始终包含
isNull(deletedAt)
完整关联查询示例、N+1反模式与动态过滤请查看examples/queries.md。
</patterns>
Additional Patterns
其他模式
The following patterns are documented with full examples in examples/:
- Query Builder - Complex filters, dynamic conditions, custom JOINs - see queries.md
- Transactions - Atomic operations, error handling, rollback - see transactions.md
- Database Migrations - Drizzle Kit workflow, vs
generate- see migrations.mdpush - Database Seeding - Development data, safe cleanup - see seeding.md
Performance optimization (indexes, prepared statements, pagination) is documented in reference.md.
<red_flags>
以下模式的完整示例请查看examples/:
- 查询构建器 - 复杂过滤、动态条件、自定义JOIN - 查看queries.md
- 事务 - 原子操作、错误处理、回滚 - 查看transactions.md
- 数据库迁移 - Drizzle Kit工作流、vs
generate- 查看migrations.mdpush - 数据库填充 - 开发数据、安全清理 - 查看seeding.md
性能优化(索引、预编译语句、分页)请查看reference.md。
<red_flags>
RED FLAGS
注意事项
- ❌ Using instead of
dbinside transactions - Bypasses transaction context, breaking atomicitytx - ❌ N+1 queries with relations - Use to fetch in one query
.with() - ❌ Not setting - Field name mismatches between JS and SQL
casing: 'snake_case' - ❌ Using v1 per-table syntax - Deprecated, use
relations()defineRelations() - ❌ Using callback-based /
where- v1 syntax deprecated, use object-based syntaxorderBy - ⚠️ Queries without soft delete checks ()
isNull(deletedAt) - ⚠️ No pagination limits on list queries
Gotchas & Edge Cases:
- Neon HTTP has 30-second query timeout - long queries need WebSocket
- Prepared statements created outside transactions cannot be used inside transactions
- deprecated in v1.0.0-beta.1 - use
enableRLS()insteadpgTable.withRLS() - Validator packages consolidated: is now
drizzle-zod(since v1 beta)drizzle-orm/zod
For the complete list of anti-patterns and gotchas, see reference.md.
</red_flags>
<critical_reminders>
- ❌ 事务中使用而非
db- 绕过事务上下文,破坏原子性tx - ❌ 关联查询出现N+1问题 - 使用单次查询获取数据
.with() - ❌ 未设置- JS与SQL字段名称不匹配
casing: 'snake_case' - ❌ 使用v1版本的单表语法 - 已废弃,使用
relations()defineRelations() - ❌ 使用回调式/
where- v1语法已废弃,使用基于对象的语法orderBy - ⚠️ 查询未包含软删除检查()
isNull(deletedAt) - ⚠️ 列表查询未设置分页限制
易犯错误与边缘情况:
- Neon HTTP查询超时时间为30秒——长查询需使用WebSocket
- 事务外创建的预编译语句无法在事务内使用
- v1.0.0-beta.1中已废弃——使用
enableRLS()替代pgTable.withRLS() - 验证器包已整合:现已改为
drizzle-zod(自v1 beta版起)drizzle-orm/zod
完整反模式与易犯错误列表请查看reference.md。
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
重要提醒
All code must follow project conventions in CLAUDE.md
(You MUST set in Drizzle config to map camelCase JS to snake_case SQL)
casing: 'snake_case'(You MUST use parameter (NOT ) inside transaction callbacks to ensure atomicity)
txdb(You MUST use for relational queries to avoid N+1 problems - fetches all data in single SQL query)
.with()(You MUST use for RQB v2 - the old per-table syntax is deprecated)
defineRelations()relations()Failure to follow these rules will cause field name mismatches, break transaction atomicity, create N+1 performance issues, and use deprecated APIs.
</critical_reminders>
所有代码必须遵循CLAUDE.md中的项目规范
(必须在Drizzle配置中设置,以将驼峰式JS字段映射为下划线式SQL字段)
casing: 'snake_case'(事务回调中必须使用参数(而非),以确保原子性)
txdb(关联查询必须使用,避免N+1问题——单次SQL查询获取所有数据)
.with()(RQB v2必须使用——旧的单表语法已废弃)
defineRelations()relations()不遵守上述规则会导致字段名称不匹配、破坏事务原子性、产生N+1性能问题,以及使用已废弃的API。
</critical_reminders>