Node.js 原生 SQLite:無需套件的輕量資料存取方案

在以往,如果你想在 Node.js 中使用 SQLite,通常需要安裝 sqlite3better-sqlite3 等第三方套件。從 Node.js 22.5.0 版本開始,Node.js 正式引入了內建的 node:sqlite 模組,讓開發者在「零外部依賴」的情況下也能輕鬆處理結構化資料。

這對於開發 CLI 工具、小型服務、或是在測試環境中模擬資料庫運作非常方便。

快速開始:建立連線

內建的 SQLite 整合在 node:sqlite 模組中。你可以選擇將資料儲存在檔案中,或是直接存在記憶體 (Memory) 中。

const { DatabaseSync } = require('node:sqlite');

// 建立一個存在硬碟的資料庫實例
const db = new DatabaseSync('./my-data.db');

// 或者建立一個僅限記憶體、程式關閉後即消失的資料庫
// const db = new DatabaseSync(':memory:');

console.log('資料庫已連線');

基礎操作:CRUD 實戰

內建的 SQLite API 採用了 同步 (Synchronous) 的設計,這在處理本地嵌入式資料庫時能避免繁瑣的 Promise 管理,且 V8 引擎在執行這類操作時效率極高。

1. 建立資料表 (Execute)

使用 exec() 方法執行不帶參數的 SQL 指令。

db.exec(`
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT UNIQUE,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
  )
`);

2. 插入資料 (Prepare & Run)

為了防止 SQL 注入 (SQL Injection) 攻擊,我們應使用 prepare() 先建立預處理陳述式,再使用 run() 傳入參數執行。

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

// 執行插入
insertUser.run('小林', 'lin@example.com');
insertUser.run('陳小姐', 'chen@example.com');

console.log('資料已成功插入');

3. 查詢資料 (Query)

  • all():回傳所有匹配的資料列(陣列)。
  • get():回傳第一筆匹配的資料(物件)。
// 查詢全部
const allUsers = db.prepare('SELECT * FROM users').all();
console.log('所有用戶:', allUsers);

// 帶條件查詢
const findUser = db.prepare('SELECT * FROM users WHERE name = ?');
const user = findUser.get('小林');
console.log('找到用戶:', user.email);

交易處理 (Transactions)

在處理多個相關聯的資料庫操作時,交易 (Transaction) 能確保資料的一致性:要麼全部成功,要麼全部失敗。

db.exec('BEGIN TRANSACTION');

try {
  const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
  insert.run('失敗案例', 'fail@example.com');

  // 假設這裡發生了商業邏輯錯誤
  // throw new Error('模擬錯誤');

  db.exec('COMMIT'); // 提交
  console.log('交易成功');
} catch (err) {
  db.exec('ROLLBACK'); // 復原
  console.error('交易失敗,已回滾:', err.message);
}

為什麼選擇原生 node:sqlite

  1. 零依賴:不需要額外下載數十 MB 的二進制編譯檔 (node-gyp),部置與打包更快速。
  2. 高效能:基於 SQLite 原生 C 語言介面直接調用,效能與主流第三方套件相當。
  3. 穩定性:由 Node.js 官方團隊維護,確保與核心版本的完美兼容。
目前的狀態node:sqlite 目前標記為實驗性 (Experimental) 功能。雖然在 Node.js 22 LTS 已經非常穩定且好用,但在生產環境中使用前,請務必確認你的 Node.js 版本符合要求,並留意 API 版本的細微變動。

總結

  1. DatabaseSync 是操作資料庫的核心類別。
  2. 務必使用 prepare() 處理參數化查詢,杜絕安全漏洞。
  3. 對於需要極致靈活與輕量的伺服器端應用,原生 SQLite 是你的首選。