mcpField
B
bun-drizzle-integration

bun-drizzle-integration

github.com/secondsky数据与数据库240425 次安装5 周前更新
代码仓库

关于 bun-drizzle-integration

介绍如何将 Drizzle ORM 与 Bun 的 SQLite 驱动结合使用,面向构建类型安全数据库访问的开发者,内容涵盖模式设置、迁移、查询和事务示例。

主要功能

  1. 01Bun SQLite 数据库设置
  2. 02类型安全的模式定义
  3. 03迁移命令
  4. 04CRUD 查询示例
  5. 05关系与事务
  6. 06预处理语句和原始 SQL

适用场景

  1. 01在 Bun 项目中设置 SQLite 访问
  2. 02定义类型安全的表和关系
  3. 03应用数据库模式迁移
  4. 04实现事务型 CRUD 操作

安装

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

$npx skills add https://github.com/secondsky/claude-skills --skill bun-drizzle-integration

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

详细介绍

Bun Drizzle 集成

Drizzle ORM 通过 Bun 的 SQLite 驱动程序提供类型安全的数据库访问。

快速开始

bun add drizzle-orm
bun add -D drizzle-kit

Schema 定义

// src/db/schema.ts
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";

export const users = sqliteTable("users", {
  id: integer("id").primaryKey({ autoIncrement: true }),
  name: text("name").notNull(),
  email: text("email").notNull().unique(),
  createdAt: integer("created_at", { mode: "timestamp" })
    .notNull()
    .default(sql`(unixepoch())`),
});

export const posts = sqliteTable("posts", {
  id: integer("id").primaryKey({ autoIncrement: true }),
  title: text("title").notNull(),
  content: text("content"),
  authorId: integer("author_id")
    .notNull()
    .references(() => users.id),
});

数据库设置

// src/db/index.ts
import { drizzle } from "drizzle-orm/bun-sqlite";
import { Database } from "bun:sqlite";
import * as schema from "./schema";

const sqlite = new Database("app.db");
export const db = drizzle(sqlite, { schema });

配置

// drizzle.config.ts
import type { Config } from "drizzle-kit";

export default {
  schema: "./src/db/schema.ts",
  out: "./drizzle",
  dialect: "sqlite",
  dbCredentials: {
    url: "./app.db",
  },
} satisfies Config;

迁移

# Generate migration
bun drizzle-kit generate

# Apply migrations
bun drizzle-kit migrate

# Push schema directly (dev only)
bun drizzle-kit push

# Open Drizzle Studio
bun drizzle-kit studio

CRUD 操作

插入
import { db } from "./db";
import { users, posts } from "./db/schema";

// Single insert
const user = await db.insert(users).values({
  name: "Alice",
  email: "[email protected]",
}).returning();

// Multiple insert
await db.insert(users).values([
  { name: "Bob", email: "[email protected]" },
  { name: "Charlie", email: "[email protected]" },
]);

// Insert or ignore
await db.insert(users)
  .values({ name: "Alice", email: "[email protected]" })
  .onConflictDoNothing();

// Upsert
await db.insert(users)
  .values({ name: "Alice", email: "[email protected]" })
  .onConflictDoUpdate({
    target: users.email,
    set: { name: "Alice Updated" },
  });
查询
import { eq, gt, like, and, or, desc, asc } from "drizzle-orm";

// All rows
const allUsers = await db.select().from(users);

// With conditions
const activeUsers = await db
  .select()
  .from(users)
  .where(eq(users.status, "active"));

// Multiple conditions
const filtered = await db
  .select()
  .from(users)
  .where(and(
    gt(users.age, 18),
    like(users.name, "%Alice%")
  ));

// Specific columns
const names = await db
  .select({ name: users.name, email: users.email })
  .from(users);

// Order and limit
const topUsers = await db
  .select()
  .from(users)
  .orderBy(desc(users.createdAt))
  .limit(10);

// First result
const first = await db.query.users.findFirst({
  where: eq(users.id, 1),
});
更新
// Update with condition
await db
  .update(users)
  .set({ name: "Alice Updated" })
  .where(eq(users.id, 1));

// Update multiple fields
await db
  .update(users)
  .set({
    name: "New Name",
    updatedAt: new Date(),
  })
  .where(eq(users.email, "[email protected]"));
删除
// Delete with condition
await db.delete(users).where(eq(users.id, 1));

// Delete multiple
await db.delete(users).where(gt(users.createdAt, cutoffDate));

关系

// schema.ts
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],
  }),
}));

// Query with relations
const usersWithPosts = await db.query.users.findMany({
  with: {
    posts: true,
  },
});

// Nested relations
const detailed = await db.query.users.findFirst({
  where: eq(users.id, 1),
  with: {
    posts: {
      with: {
        comments: true,
      },
    },
  },
});

事务

// Transaction
await db.transaction(async (tx) => {
  const [user] = await tx.insert(users)
    .values({ name: "Alice", email: "[email protected]" })
    .returning();

  await tx.insert(posts).values({
    title: "First Post",
    authorId: user.id,
  });
});

// Rollback on error
await db.transaction(async (tx) => {
  await tx.insert(users).values({ name: "Bob" });

  if (someCondition) {
    tx.rollback(); // Throws to rollback
  }

  await tx.insert(posts).values({ ... });
});

预处理语句

// Create prepared statement
const getUserById = db
  .select()
  .from(users)
  .where(eq(users.id, sql.placeholder("id")))
  .prepare();

// Execute with parameter
const user = await getUserById.execute({ id: 1 });

// Reuse for performance
for (const id of userIds) {
  const user = await getUserById.execute({ id });
  processUser(user);
}

原始 SQL

import { sql } from "drizzle-orm";

// Raw query
const result = await db.run(sql`
  UPDATE users SET last_login = ${new Date()} WHERE id = ${userId}
`);

// In select
const users = await db.select({
  name: users.name,
  upperName: sql<string>`UPPER(${users.name})`,
}).from(users);

// Raw expressions in where
await db.select().from(users).where(
  sql`${users.age} > 18 AND ${users.status} = 'active'`
);

列类型参考

import {
  sqliteTable,
  text,
  integer,
  real,
  blob,
  numeric,
} from "drizzle-orm/sqlite-core";

const example = sqliteTable("example", {
  // Integer
  id: integer("id").primaryKey(),
  age: integer("age"),

  // Text
  name: text("name"),
  status: text("status", { enum: ["active", "inactive"] }),

  // Real (float)
  price: real("price"),

  // Blob
  data: blob("data", { mode: "buffer" }),

  // Boolean (stored as integer)
  active: integer("active", { mode: "boolean" }),

  // Timestamp (stored as integer)
  createdAt: integer("created_at", { mode: "timestamp" }),
  updatedMs: integer("updated_ms", { mode: "timestamp_ms" }),

  // JSON (stored as text)
  metadata: text("metadata", { mode: "json" }),
});

常见错误

错误原因解决方法
SQLITE_CONSTRAINT外键/唯一性约束冲突检查约束
no such columnSchema 不匹配运行迁移
Cannot find module缺少驱动程序使用 drizzle-orm/bun-sqlite
类型不匹配列类型错误检查 Schema 定义

何时加载参考资料

在以下情况下加载 references/migrations.md:

  • 复杂的迁移场景
  • 合并迁移
  • 数据库填充

在以下情况下加载 references/performance.md:

  • 查询优化
  • 索引策略
  • 连接池

评论

支持 Markdown