BunSQLite BunSQLite

Bun SQLite 是一个用于 Bun 环境的 SQLite 数据库驱动程序,提供高性能的 SQLite 操作,包括准备语句、事务处理和查询执行。适用于后端开发、数据存储和应用程序开发,提升数据库交互效率和性能。关键词:Bun, SQLite, 数据库, 后端开发, 数据存储, 高性能, 准备语句, 事务处理, 查询执行, 应用程序开发。

后端开发 0 次安装 0 次浏览 更新于 3/8/2026

name: Bun SQLite description: 用于bun:sqlite,SQLite操作,准备语句,事务和查询。 version: 1.0.0

Bun SQLite

Bun 通过 bun:sqlite 拥有一个内置的高性能 SQLite 驱动程序。

快速开始

import { Database } from "bun:sqlite";

// 创建/打开数据库
const db = new Database("mydb.sqlite");

// 创建表
db.run(`
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT UNIQUE
  )
`);

// 插入数据
db.run("INSERT INTO users (name, email) VALUES (?, ?)", ["Alice", "alice@example.com"]);

// 查询数据
const users = db.query("SELECT * FROM users").all();
console.log(users);

// 关闭
db.close();

打开数据库

import { Database } from "bun:sqlite";

// 文件基础数据库
const db = new Database("data.sqlite");

// 内存数据库
const memDb = new Database(":memory:");

// 只读模式
const readDb = new Database("data.sqlite", { readonly: true });

// 如果不存在则创建(默认)
const createDb = new Database("new.sqlite", { create: true });

// 严格模式(推荐)
const strictDb = new Database("strict.sqlite", { strict: true });

运行查询

直接执行

// 运行(用于 INSERT, UPDATE, DELETE, DDL)
db.run("CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT)");
db.run("INSERT INTO items (name) VALUES (?)", ["Item 1"]);
db.run("DELETE FROM items WHERE id = ?", [1]);

// 获取更改信息
const result = db.run("DELETE FROM items WHERE id > ?", [10]);
console.log(result.changes); // 受影响的行数
console.log(result.lastInsertRowid); // 最后插入的ID

准备语句(推荐)

// 创建准备语句
const stmt = db.prepare("SELECT * FROM users WHERE id = ?");

// 获取单行
const user = stmt.get(1);

// 获取所有行
const allUsers = db.prepare("SELECT * FROM users").all();

// 获取值作为数组
const values = db.prepare("SELECT name, email FROM users").values();
// [[name1, email1], [name2, email2], ...]

// 使用 for...of 迭代
const iter = db.prepare("SELECT * FROM users");
for (const user of iter.iterate()) {
  console.log(user);
}

参数

位置参数

const stmt = db.prepare("INSERT INTO users (name, email) VALUES (?, ?)");
stmt.run("Bob", "bob@example.com");

// 或作为数组
stmt.run(["Charlie", "charlie@example.com"]);

命名参数

const stmt = db.prepare("INSERT INTO users (name, email) VALUES ($name, $email)");
stmt.run({ $name: "Dave", $email: "dave@example.com" });

// 也适用于 : 和 @
const stmt2 = db.prepare("SELECT * FROM users WHERE name = :name");
stmt2.get({ name: "Dave" }); // 注意:对象键中没有冒号

查询方法

const stmt = db.prepare("SELECT * FROM users WHERE active = ?");

// .get() - 第一行或 null
const first = stmt.get(true);

// .all() - 所有行作为数组
const all = stmt.all(true);

// .values() - 行作为数组(非对象)
const values = stmt.values(true);
// [[1, "Alice", true], [2, "Bob", true]]

// .iterate() - 迭代器以提高内存效率
for (const row of stmt.iterate(true)) {
  processRow(row);
}

// .run() - 执行而不返回数据
db.prepare("DELETE FROM cache WHERE expires < ?").run(Date.now());

事务

// 简单事务
const insertMany = db.transaction((users: { name: string; email: string }[]) => {
  const insert = db.prepare("INSERT INTO users (name, email) VALUES ($name, $email)");
  for (const user of users) {
    insert.run(user);
  }
  return users.length;
});

const count = insertMany([
  { name: "User1", email: "user1@example.com" },
  { name: "User2", email: "user2@example.com" },
]);

// 事务模式
const tx = db.transaction(() => {
  db.run('INSERT INTO users (name, email) VALUES (?, ?)', ['Alice', 'alice@example.com']);
  db.run('UPDATE accounts SET balance = balance - 100 WHERE user_id = ?', [1]);
});

tx.deferred();   // 默认:延迟锁定直到第一次写入
tx.immediate();  // 在事务开始时立即锁定
tx.exclusive();  // 排他锁定,阻止所有其他连接

批处理操作

// WAL 模式以提高并发性能
db.run("PRAGMA journal_mode = WAL");

// 使用事务进行批量插入
const insertBulk = db.transaction((items: string[]) => {
  const stmt = db.prepare("INSERT INTO items (name) VALUES (?)");
  for (const item of items) {
    stmt.run(item);
  }
});

insertBulk(["A", "B", "C", "D", "E"]);

列类型

// SQLite 类型映射到 JavaScript
/*
  SQLite      JavaScript
  ------      ----------
  INTEGER     数字 | 大整数
  REAL        数字
  TEXT        字符串
  BLOB        Uint8Array
  NULL        null
*/

// 处理大整数
const bigStmt = db.prepare("SELECT COUNT(*) as count FROM users");
const result = bigStmt.get();
// 如果大于 Number.MAX_SAFE_INTEGER,result.count 可能是 bigint

// 存储/检索 Uint8Array
db.run("INSERT INTO files (data) VALUES (?)", [new Uint8Array([1, 2, 3])]);
const file = db.prepare("SELECT data FROM files WHERE id = ?").get(1);
// file.data 是 Uint8Array

列定义

// 获取列信息
const stmt = db.prepare("SELECT * FROM users");
const columns = stmt.columnNames;
// ["id", "name", "email"]

// 类型注释(Bun 扩展)
const typedStmt = db.prepare<{ id: number; name: string }, [number]>(
  "SELECT id, name FROM users WHERE id = ?"
);
const user = typedStmt.get(1);
// user 被类型化为 { id: number; name: string } | null

错误处理

import { Database, SQLiteError } from "bun:sqlite";

try {
  db.run("INSERT INTO users (email) VALUES (?)", ["duplicate@example.com"]);
} catch (error) {
  if (error instanceof SQLiteError) {
    console.error("SQLite 错误:", error.code, error.message);
    // error.code: "SQLITE_CONSTRAINT_UNIQUE"
  }
  throw error;
}

数据库管理

// 关闭数据库
db.close();

// 检查是否打开
console.log(db.inTransaction); // 是否在事务中

// 序列化为缓冲区
const buffer = db.serialize();
await Bun.write("backup.sqlite", buffer);

// 从缓冲区加载
const data = await Bun.file("backup.sqlite").arrayBuffer();
const restored = Database.deserialize(data);

// 文件名
console.log(db.filename); // 路径或 ":memory:"

常见模式

仓库模式

import { Database } from "bun:sqlite";

interface User {
  id: number;
  name: string;
  email: string;
}

class UserRepository {
  private db: Database;
  private stmts: {
    findById: ReturnType<Database["prepare"]>;
    findAll: ReturnType<Database["prepare"]>;
    create: ReturnType<Database["prepare"]>;
    update: ReturnType<Database["prepare"]>;
    delete: ReturnType<Database["prepare"]>;
  };

  constructor(db: Database) {
    this.db = db;
    this.stmts = {
      findById: db.prepare("SELECT * FROM users WHERE id = ?"),
      findAll: db.prepare("SELECT * FROM users"),
      create: db.prepare("INSERT INTO users (name, email) VALUES ($name, $email)"),
      update: db.prepare("UPDATE users SET name = $name, email = $email WHERE id = $id"),
      delete: db.prepare("DELETE FROM users WHERE id = ?"),
    };
  }

  findById(id: number): User | null {
    return this.stmts.findById.get(id) as User | null;
  }

  findAll(): User[] {
    return this.stmts.findAll.all() as User[];
  }

  create(user: Omit<User, "id">): number {
    const result = this.stmts.create.run(user);
    return Number(result.lastInsertRowid);
  }
}

常见错误

错误 原因 修复
SQLITE_CONSTRAINT 约束违反 检查 UNIQUE/FK 约束
SQLITE_BUSY 数据库锁定 使用 WAL 模式,添加重试逻辑
no such table 表不存在 先运行 CREATE TABLE
database is locked 并发访问 启用 WAL 模式

性能提示

-- 启用 WAL 模式(更好的并发性)
PRAGMA journal_mode = WAL;

-- 更快的写入(较少持久性)
PRAGMA synchronous = NORMAL;

-- 增加缓存大小
PRAGMA cache_size = 10000;

-- 启用外键
PRAGMA foreign_keys = ON;

何时加载参考资料

加载 references/pragmas.md 当:

  • 性能调优
  • 日志模式
  • 内存配置

加载 references/fts.md 当:

  • 全文搜索
  • FTS5 配置