创新方案
在 Bun 项目中使用 bun:sqlite…
当运行环境是 Bun 且需要本地嵌入式 SQLite 数据库时,用 bun:sqlite 完成建表、参数化查询、事务、备份和常用优化。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在 Bun 项目中使用 bun:sqli特定
解决思路
- 用 `import { Database } from 'bun:sqlite';` 引入 Bun 内置 SQLite 驱动。
- 用 `const db = new Database('mydb.sqlite');` 创建或打开数据库。
- 用 `db.run(\`CREATE TABLE IF NOT EXISTS users (...)\`)` 创建表。
- 用 `db.run('INSERT INTO users (name, email) VALUES (?, ?)', ['Alice', 'alice@example.com'])` 插入数据。
- 用 `db.query('SELECT * FROM users').all()` 查询数据。
- 用 `db.close()` 关闭数据库。
- 用 `new Database('data.sqlite')` 打开文件数据库。
- 用 `new Database(':memory:')` 打开内存数据库。
- 用 `new Database('data.sqlite', { readonly: true })` 以只读模式打开数据库。
- 用 `new Database('new.sqlite', { create: true })` 在数据库不存在时创建(默认行为)。
- 用 `new Database('strict.sqlite', { strict: true })` 启用严格模式(推荐)。
- 用 `db.run` 执行 INSERT、UPDATE、DELETE、DDL 等直接 SQL。
- 从 `db.run` 返回对象读取 `changes` 获取影响行数,读取 `lastInsertRowid` 获取最后插入 ID。
- 用 `db.prepare('SELECT * FROM users WHERE id = ?')` 创建预编译语句。
- 用 `stmt.get(1)` 获取单行结果。
- 用 `db.prepare('SELECT * FROM users').all()` 获取所有行。
- 用 `db.prepare('SELECT name, email FROM users').values()` 将行作为数组返回。
- 用 `iter.iterate()` 配合 `for...of` 迭代查询结果以节省内存。
- 位置参数:SQL 中用 `?`,调用 `stmt.run('Bob', 'bob@example.com')` 或传数组 `stmt.run(['Charlie', 'charlie@example.com'])`。
- 命名参数:SQL 中用 `$name`、`$email`,调用 `stmt.run({ $name: 'Dave', $email: 'dave@example.com' })`。
- 命名参数也支持 `:name` 和 `@name`;用 `:name` 时对象键为 `name`,如 `stmt2.get({ name: 'Dave' })`。
- 用 `.get()` 返回首行或 null。
- 用 `.all()` 返回所有行对象数组。
- 用 `.values()` 返回行数组而非对象。
- 用 `.iterate()` 返回迭代器。
- 用 `.run()` 执行不返回数据的语句。
- 用 `db.transaction((users) => { ... })` 包装事务;在回调中用 `db.prepare` 和循环 `insert.run(user)`;可返回结果。
- 事务模式:`tx.deferred()` 默认延迟到首次写入才加锁。
- 事务模式:`tx.immediate()` 在事务开始时立即加锁。
- 事务模式:`tx.exclusive()` 使用排他锁并阻止其他连接。
- 批量操作:执行 `db.run('PRAGMA journal_mode = WAL')` 提高并发性能。
- 批量操作:把批量插入放入 `db.transaction`,在事务内用 `db.prepare('INSERT INTO items (name) VALUES (?)')` 并循环 `stmt.run(item)`。
- 列类型映射:INTEGER -> number | bigint;REAL -> number;TEXT -> string;BLOB -> Uint8Array;NULL -> null。
- 大整数可能返回 bigint,如 `SELECT COUNT(*)` 结果可能为 bigint。
- 用 `Uint8Array` 存储和读取 BLOB,如 `db.run('INSERT INTO files (data) VALUES (?)', [new Uint8Array([1, 2, 3])])`,查询后 `file.data` 是 `Uint8Array`。
- 用 `stmt.columnNames` 获取列名数组。
- 用 Bun 扩展类型标注:`db.prepare<{ id: number; name: string }, [number]>('SELECT id, name FROM users WHERE id = ?')`。
- 错误处理:从 `bun:sqlite` 导入 `SQLiteError`。
- 用 try/catch 捕获,检查 `error instanceof SQLiteError`,读取 `error.code` 和 `error.message`;否则重新抛出。
- 数据库管理:用 `db.close()` 关闭数据库。
- 用 `db.inTransaction` 检查是否在事务中。
- 用 `db.serialize()` 序列化为 buffer,并用 `await Bun.write('backup.sqlite', buffer)` 备份。
- 用 `await Bun.file('backup.sqlite').arrayBuffer()` 读取备份,用 `Database.deserialize(data)` 恢复。
- 用 `db.filename` 获取路径或 `:memory:`。
- Repository Pattern:类中持有 `Database` 和预编译语句对象,并用 `ReturnType<Database['prepare']>` 定义语句类型;构造时用 `db.prepare` 创建 findById/findAll/create/update/delete 语句。
- Repository Pattern:方法中用 `.get`、`.all`、`.run`;create 中用 `Number(result.lastInsertRowid)` 返回插入 ID。
- 常见错误:`SQLITE_CONSTRAINT` 检查 UNIQUE/FK 约束。
- 常见错误:`SQLITE_BUSY` 使用 WAL 模式并添加重试逻辑。
- 常见错误:`no such table` 先运行 CREATE TABLE。
- 常见错误:`database is locked` 启用 WAL 模式。
- 性能调优:执行 `PRAGMA journal_mode = WAL;`。
- 性能调优:执行 `PRAGMA synchronous = NORMAL;` 加快写入但降低持久性。
- 性能调优:执行 `PRAGMA cache_size = 10000;` 增加缓存。
- 性能调优:执行 `PRAGMA foreign_keys = ON;` 启用外键。
- 按需加载 `references/pragmas.md` 当进行性能调优、日志模式、内存配置时。
- 按需加载 `references/fts.md` 当进行全文搜索、FTS5 配置时。
适用边界 · 注意事项
- 运行环境不是 Bun 时不能用 `bun:sqlite`,应改用该运行时的 SQLite 库(如 Node.js 的 `node:sqlite` 或 `better-sqlite3`)。
- 需要远程访问数据库、多写入者高并发或客户端/服务端分离架构时,SQLite 嵌入式模型不适合。
- 不想为项目引入 Bun 运行时依赖时,不应使用此技能。