Bun + SQLite 10个实用技巧

40岁了, 还在写JS

先看参数化查询 ------ 安全、简洁、防注入:

ts 复制代码
import { Database } from "bun:sqlite";

const db = new Database("app.db");
const userInput = "Alice";  // 恶意输入 '; DROP TABLE users; -- 也会被转义

db.run("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)");
db.run("INSERT INTO users (name) VALUES (?)", [userInput]);

const user = db.query("SELECT * FROM users WHERE name = ?").get(userInput);
console.log(user);

下面 10 个技巧,让你在 Bun 中把 SQLite 用到极致。


1. 参数化查询:防注入唯一正解

永远用 ? 占位符传值,绝不拼接字符串。

ts 复制代码
const insert = db.prepare("INSERT INTO logs (level, msg) VALUES (?, ?)");
insert.run("INFO", "系统启动");

const search = db.query("SELECT * FROM logs WHERE level = ?");
const errors = search.all("ERROR");

2. 内存+WAL:极速与并发

内存数据库临时用,WAL 模式提升读写并发。

ts 复制代码
const memDb = new Database(":memory:");

db.exec("PRAGMA journal_mode = WAL");
db.exec("PRAGMA synchronous = NORMAL");

3. 批量事务:每秒五万写入

事务包裹预编译语句,批量插入效率暴增。

ts 复制代码
const stmt = db.prepare("INSERT INTO sensors (val) VALUES (?)");
const batch = db.transaction((arr) => {
  for (const v of arr) stmt.run(v);
});
batch([1, 2, 3, 4, 5]);

4. JSON 支持:像 NoSQL 一样

直接存 JSON,按字段查询,省掉文档数据库。

ts 复制代码
db.run("CREATE TABLE cfg (key TEXT, val JSON)");
db.run("INSERT INTO cfg VALUES (?, ?)", ["theme", JSON.stringify({ dark: true })]);

const dark = db.query("SELECT json_extract(val, '$.dark') FROM cfg").get();

5. 全文检索:轻量搜索引擎

FTS5 虚拟表,日志搜索毫秒级响应。

ts 复制代码
db.exec("CREATE VIRTUAL TABLE posts USING fts5(title, body)");
db.exec("INSERT INTO posts VALUES ('Bun 发布', '速度极快')");

const res = db.query("SELECT * FROM posts WHERE posts MATCH '速度'").all();

6. 递归 CTE:树形查询一行

组织架构、菜单树,一条 SQL 搞定层级遍历。

ts 复制代码
db.exec("CREATE TABLE dept(id INT, name TEXT, pid INT)");

const tree = db.query(`
  WITH RECURSIVE t AS (
    SELECT id, name, 0 lvl FROM dept WHERE pid IS NULL
    UNION ALL
    SELECT d.id, d.name, t.lvl + 1 FROM dept d JOIN t ON d.pid = t.id
  )
  SELECT * FROM t
`).all();

7. 窗口函数:移动平均排名

环比、同比、排名,无需子查询。

ts 复制代码
db.exec("CREATE TABLE sales(month TEXT, amt INT)");

const avg = db.query(`
  SELECT month, amt,
         AVG(amt) OVER (ORDER BY month ROWS 1 PRECEDING) as prev_avg
  FROM sales
`).all();

8. 生成列:自动计算属性

面积、全名等派生字段,数据库自动维护。

ts 复制代码
db.exec(`
  CREATE TABLE rect(
    w REAL,
    h REAL,
    area REAL GENERATED ALWAYS AS (w * h) STORED
  )
`);
db.run("INSERT INTO rect(w, h) VALUES (3, 4)");

const a = db.query("SELECT area FROM rect").get(); // 12

9. 外键级联:数据完整性

开启外键,删除主表自动清理子表。

ts 复制代码
db.exec("PRAGMA foreign_keys = ON");
db.exec("CREATE TABLE users(id INT PRIMARY KEY)");
db.exec(`
  CREATE TABLE orders(
    id INT,
    uid INT REFERENCES users(id) ON DELETE CASCADE
  )
`);
db.run("DELETE FROM users WHERE id = 1"); // 自动删订单

10. 触发器+清理:自动维护与回收

更新时间戳自动更新,定期 VACUUM 释放空间。

ts 复制代码
db.exec(`
  CREATE TRIGGER update_time
  AFTER UPDATE ON todos
  BEGIN
    UPDATE todos SET updated_at = CURRENT_TIMESTAMP WHERE id = NEW.id;
  END;
`);

db.exec("DELETE FROM logs WHERE ts < strftime('%s', 'now', '-7 days')");
db.exec("VACUUM");

总结

参数化查询保安全,JSON+全文检索扩能力,窗口+递归解难题,事务+WAL 提性能。Bun 让 SQLite 在边缘设备和桌面应用中都如鱼得水。

相关推荐
techdashen10 小时前
Arborium:把 tree-sitter 语法高亮打包成 Rust 文档生态的基础设施
开发语言·后端·rust
Profile排查笔记10 小时前
指纹浏览器环境异常排查:Fingerprint、Profile、Proxy、Session 和 Task Log 怎么看
前端·人工智能·后端·自动化
京韵养生记10 小时前
【无标题】
java·服务器·前端
小强库计算机毕业设计10 小时前
源码分享Spring Boot + Vue3 的校园社团管理系统
java·spring boot·后端·计算机毕业设计
阿新聊ai11 小时前
从 Prompt 到 Loop:AI 编程 Agent 四代循环的演进全景
人工智能·后端
im_lanny11 小时前
从 Function Calling 到 MCP:Agent 工具调用的三层境界与生产级安全护栏
后端
大气的小蜜蜂11 小时前
领域层的服务
java·前端·数据库
agent89711 小时前
Spring Boot 接口超时治理:从连接池、线程池到熔断限流的完整排查思路
java·spring boot·后端
星栈11 小时前
LiveView 的 LiveComponent:比 React 组件更轻,但我一开始真的把它用错了
前端·前端框架·elixir
竹林81811 小时前
用 Pinata + IPFS 存 NFT 元数据踩了三天坑,我总结了这份完整的前端实现方案
javascript