mcpField
D
drizzle-orm-v0

drizzle-orm-v0

github.com/blockmatic数据与数据库1222 次安装4 周前更新
代码仓库

关于 drizzle-orm-v0

面向使用 Drizzle ORM v0.45+ 的 TypeScript 开发者,提供 PostgreSQL、MySQL 和 SQLite 的模式、类型安全查询与迁移实践。重点涵盖类型推导、Drizzle Kit 迁移和事务。

主要功能

  1. 01定义带类型的数据库表和列
  2. 02构建类型安全查询
  3. 03通过 Drizzle Kit 管理迁移
  4. 04使用类型推导生成记录类型
  5. 05以事务执行多步操作

适用场景

  1. 01为 PostgreSQL、MySQL 或 SQLite 建立模式
  2. 02编写类型安全的 CRUD 查询
  3. 03生成并应用数据库迁移
  4. 04确保多步数据库操作保持原子性

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/blockmatic/basilic-skills --skill drizzle-orm-v0

安装后在 Claude Code 中输入/drizzle-orm-v0确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
postgresql-patterns.md
queries.md
templates/
db.ts
schema.ts

详细介绍

技能:drizzle-orm

适用范围

  • 适用于:Drizzle ORM v0.45+,用于 PostgreSQL、MySQL、SQLite,包括模式定义、类型安全查询和迁移
  • 不涵盖:数据库驱动设置、连接池配置、其他 ORM

前提条件

  • Drizzle ORM v0.45+
  • Drizzle Kit v0.31+(开发依赖),用于迁移
  • PostgreSQL、MySQL 或 SQLite 数据库
  • TypeScript v5+,启用严格模式
  • ESM 模块系统

原则

  • 使用表构建器(pgTable、mysqlTable、sqliteTable)定义模式,并为列指定类型
  • 列类型与数据库约束相匹配(例如,varchar 指定长度,timestamp 指定模式)
  • 在表定义的第二个参数中使用 index() 辅助函数定义索引
  • 带有 .references() 外键的文本主键是有效的默认选择
  • 查询辅助函数(eq、and、or、like)可用于构建类型安全的 SQL
  • 使用 $inferSelect 和 $inferInsert 推导类型,避免手动定义类型
  • 使用 drizzle-kit generate 生成迁移(生产环境中不要使用 push)
  • 使用预处理语句优化频繁执行的查询
  • 按领域组织模式(每个实体/表一个文件)
  • 使用事务(db.transaction)确保多步操作的原子性

约束

必须
  • 使用 Drizzle Kit 执行迁移(drizzle-kit generate、drizzle-kit migrate)
  • 定义与数据库约束相匹配的列类型
  • 使用查询辅助函数,而非原始 SQL
应当
  • 对多步操作使用事务
  • 对频繁执行的查询使用预处理语句
  • 使用 $inferSelect 和 $inferInsert 导出类型
  • 通过 DrizzleQueryError 进行结构化错误处理
  • 按领域组织模式(每个实体一个文件)
  • 选择性加载字段(而非完整行)
  • 为 varchar 列指定长度
  • 在表定义中使用 index() 辅助函数
  • 使用 PGLite 测试 PostgreSQL 模式
  • 如果项目已在使用 relations(),则使用它和关系查询构建器
可选
  • 在 PostgreSQL 中使用标识列(generatedAlwaysAsIdentity)代替 serial
  • 定义了关系时,可对复杂联接使用关系查询构建器(db.query.*)
避免
  • 除非必要,否则避免使用原始 SQL
  • 避免手动进行类型断言(使用推导类型)
  • 避免跳过迁移生成
  • 避免在新的 PostgreSQL 表中使用 serial(改用标识列)
  • 避免过度创建索引(仅在查询有需要时创建)
  • 仅需少数几列时,避免获取完整行
  • 避免在生产环境中使用 push(使用 generate + migrate)
  • 数据库支持日期/时间类型时,避免使用基于字符串的时间戳模式

交互

  • 可与 next Server Components 和 API 路由配合使用
  • 可与 fastify 配合进行 API 开发

模式

模式定义
import { index, pgTable, text, timestamp, varchar } from 'drizzle-orm/pg-core'

export const users = pgTable(
  'users',
  {
    id: text('id').primaryKey(),
    email: varchar('email', { length: 255 }).notNull().unique(),
    createdAt: timestamp('created_at').defaultNow().notNull(),
    updatedAt: timestamp('updated_at').defaultNow().notNull(),
  },
  table => [index('users_email_idx').on(table.email)],
)

export type User = typeof users.$inferSelect
export type NewUser = typeof users.$inferInsert
标识列
import { pgTable, integer, generatedAlwaysAsIdentity } from 'drizzle-orm/pg-core'

export const posts = pgTable('posts', {
  id: integer('id').primaryKey().generatedAlwaysAsIdentity(),
})
查询构建器
import { eq } from 'drizzle-orm'

const user = await db
  .select()
  .from(users)
  .where(eq(users.id, userId))
  .limit(1)

const userWithPosts = await db.query.users.findFirst({
  where: eq(users.id, userId),
  with: { posts: true },
})

const userEmail = await db
  .select({ email: users.email })
  .from(users)
  .where(eq(users.id, userId))
事务
await db.transaction(async (tx) => {
  const [user] = await tx.insert(users).values(userData).returning()
  await tx.insert(profiles).values({ userId: user.id, ...profileData })
})
预处理语句
import { placeholder } from 'drizzle-orm'

const getUserByEmail = db
  .select()
  .from(users)
  .where(eq(users.email, placeholder('email')))
  .prepare('get_user_by_email')

const user = await getUserByEmail.execute({ email: '[email protected]' })
错误处理
import { DrizzleQueryError } from 'drizzle-orm'

try {
  const user = await db.select().from(users).where(eq(users.id, userId))
} catch (error) {
  if (error instanceof DrizzleQueryError) {
    if (error.cause?.code === '23505') {
      throw new Error('User already exists')
    }
  }
  throw error
}
关系
import { relations } from 'drizzle-orm'

export const usersRelations = relations(users, ({ many }) => ({
  posts: many(posts),
}))

export const postsRelations = relations(posts, ({ one }) => ({
  author: one(users, {
    fields: [posts.authorId],
    references: [users.id],
  }),
}))
数据库连接
import { drizzle } from 'drizzle-orm/node-postgres'
import { Pool } from 'pg'
import * as schema from './schema'

const pool = new Pool({ connectionString: process.env.DATABASE_URL })
export const db = drizzle(pool, { schema })
Drizzle Kit 配置
import { defineConfig } from 'drizzle-kit'

export default defineConfig({
  dialect: 'postgresql',
  schema: './src/db/schema/index.ts',
  out: './src/db/migrations',
  dbCredentials: { url: process.env.DATABASE_URL! },
  migrations: {
    table: '__drizzle_migrations',
    schema: 'public',
  },
  verbose: true,
  strict: true,
})

参考资料

评论

支持 Markdown