重磅!Node.js 24 原生 SQLite 支持

88 阅读3分钟

Node.js 24 引入了对 SQLite 的原生支持,通过内置模块 node:sqlite,我们不再需要依赖第三方库(如 better-sqlite3sqlite3)即可高效操作 SQLite 数据库。该模块提供了同步 API,适用于脚本、工具或轻量级服务。


1. 准备工作

确保你使用的是 Node.js v24+(推荐 v24.7.0 或更高):

node -v
# v24.7.0

2. 基本 API 简介

  • DatabaseSync:代表一个 SQLite 数据库连接(同步)。
  • database.prepare(sql):编译 SQL 语句为预处理语句。
  • statement.run(...):执行 INSERT/UPDATE/DELETE,返回变更信息。
  • statement.get(...):查询单行结果。
  • statement.all(...):查询所有结果。

所有操作均为 同步,适合 CLI 工具、测试脚本、小型应用。


3. 示例:用户 CRUD 操作

我们将实现一个内存数据库,包含 users 表,支持增删改查。

3.1 创建数据库与表

// user-crud.mjs
import { DatabaseSync } from 'node:sqlite';

// 使用内存数据库(也可替换为 'users.db')
const db = new DatabaseSync(':memory:');

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

STRICT 表示启用 SQLite 的严格表模式,增强类型安全。


3.2 创建用户(Create)

const insertUser = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)');

function createUser(name, email) {
  const result = insertUser.run(name, email);
  return { id: result.lastInsertRowid, name, email };
}

run() 返回包含 lastInsertRowidchanges 的对象。


3.3 查询用户(Read)

const findUserById = db.prepare('SELECT * FROM users WHERE id = ?');
const findAllUsers = db.prepare('SELECT * FROM users');

function getUserById(id) {
  return findUserById.get(id) || null;
}

function listAllUsers() {
  return findAllUsers.all();
}
  • get():返回第一条记录(对象)或 undefined
  • all():返回所有记录(数组)。

3.4 更新用户(Update)

const updateUserStmt = db.prepare('UPDATE users SET name = ?, email = ? WHERE id = ?');

function updateUser(id, name, email) {
  const result = updateUserStmt.run(name, email, id);
  return result.changes > 0; // 返回是否成功更新
}

3.5 删除用户(Delete)

const deleteUserStmt = db.prepare('DELETE FROM users WHERE id = ?');

function deleteUser(id) {
  const result = deleteUserStmt.run(id);
  return result.changes > 0;
}

4. 完整运行示例

// user-crud.mjs
import { DatabaseSync } from 'node:sqlite';

const db = new DatabaseSync(':memory:');

db.exec(`
  CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT UNIQUE NOT NULL
  ) STRICT
`);

// Prepare statements
const insertUser = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
const findUserById = db.prepare('SELECT * FROM users WHERE id = ?');
const findAllUsers = db.prepare('SELECT * FROM users');
const updateUserStmt = db.prepare('UPDATE users SET name = ?, email = ? WHERE id = ?');
const deleteUserStmt = db.prepare('DELETE FROM users WHERE id = ?');

// CRUD functions
function createUser(name, email) {
  const result = insertUser.run(name, email);
  return { id: result.lastInsertRowid, name, email };
}

function getUserById(id) {
  return findUserById.get(id) || null;
}

function listAllUsers() {
  return findAllUsers.all();
}

function updateUser(id, name, email) {
  const result = updateUserStmt.run(name, email, id);
  return result.changes > 0;
}

function deleteUser(id) {
  const result = deleteUserStmt.run(id);
  return result.changes > 0;
}

// 示例使用
const user1 = createUser('Alice', 'alice@example.com');
console.log('Created:', user1);

const user2 = createUser('Bob', 'bob@example.com');
console.log('Created:', user2);

console.log('All users:', listAllUsers());

updateUser(user1.id, 'Alice Cooper', 'alice.cooper@example.com');
console.log('Updated Alice:', getUserById(user1.id));

deleteUser(user2.id);
console.log('Bob deleted, remaining users:', listAllUsers());

// 关闭数据库(可选,内存数据库退出即销毁)
db.close();

运行:

node user-crud.mjs

输出示例:

Created: { id: 1n, name: 'Alice', email: 'alice@example.com' }
Created: { id: 2n, name: 'Bob', email: 'bob@example.com' }
All users: [
  { id: 1n, name: 'Alice', email: 'alice@example.com' },
  { id: 2n, name: 'Bob', email: 'bob@example.com' }
]
Updated Alice: { id: 1n, name: 'Alice Cooper', email: 'alice.cooper@example.com' }
Bob deleted, remaining users: [
  { id: 1n, name: 'Alice Cooper', email: 'alice.cooper@example.com' }
]

注意:idBigInt(后缀 n),因为 SQLite 的 ROWID 可能超过 JS Number 安全范围。可通过 readBigInts: false 选项改为 number。


5. 高级提示

5.1 使用命名参数(更清晰)

const stmt = db.prepare('SELECT * FROM users WHERE email = :email');
const user = stmt.get({ email: 'alice@example.com' });

5.2 自动关闭(使用 using 语句,Node.js 21+)

// 需开启 --harmony-explicit-resource-management
using db = new DatabaseSync(':memory:');
// 自动调用 db[Symbol.dispose]()

5.3 文件数据库 vs 内存数据库

  • ':memory:':临时数据库,进程结束即销毁。
  • './app.db':持久化到文件。

6. 总结

Node.js 24 的 node:sqlite 模块提供了:

✅ 零依赖
✅ 同步 API,简单直接
✅ 支持预处理语句(防 SQL 注入)
✅ 内置事务、备份、扩展支持

非常适合:

  • 脚本工具

  • 本地应用

  • 测试数据库

  • 小型 Web 服务(配合 Worker Threads)