iT邦幫忙

2026 iThome 鐵人賽

DAY 11
0

title

前言

bun 從 v0.6 版之後就內建了 bun:sqlite 的模組不需要額外安裝依賴(像是 better-sqlite3)
這個功能可以做非常多不錯的操作,且減少不少 js 綁定的額外開銷以及相容性問題,
所以今天我想特別講一下這一段

近期 nodejs 在 v26.5.0 才有 sqlite 的模組使用,詳見 nodejs_v26.5_sqlite
也就是說,這樣的功能 bun 走得相當早,也相當有先見之明。

我們這裡開始開箱使用

我們這裡先建立的簡單的 CRUD 作為示範

import { Database } from 'bun:sqlite';

// 建立資料庫,並且存在 mydb.sqlite 
const db = new Database('mydb.sqlite');

// 建立一個 users 資料表
db.run(`
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT UNIQUE
  )
`)

// 來建立簡單的 CRUD

// create(insert) 插入一個資料
const insert = db.prepare('INSERT INTO users (name, email) VALUES (?, ?)');
insert.run('Michael', 'michael@gmail.com')

// Read(query) 查一下資料
const query = db.prepare('SELECT * FROM users WHERE name = ?');
const user = query.get('Michael');
console.log(user);

我們看看執行結果

result_crud

記憶體模式

我們在這裡這樣寫,如果 new Database() 這裏不傳入任何參數,這時候會把相應結果存在記憶體內

// 建立資料庫,這樣會存在記憶體
const db = new Database();

好處 :

  • 可以做一些小型服務
  • 可以建立乾淨的測試資料庫

常見查詢操作

  • 取得單一使用者
  • 取得多筆使用者
import { Database } from 'bun:sqlite'

const db = new Database();

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

const stmtInserted = db.prepare(`
  INSERT INTO users (name, email) VALUES 
  ('Michael', 'Michael@gmail.com'),
  ('Mike', 'Mike@gmail.com'),
  ('Angela', 'Angela@gmail.com')
`)

stmtInserted.run();

// 取得一筆

const stmtSingle = db.prepare(`
  SELECT * FROM users WHERE id = ?
`)

const singleUser = stmtSingle.get(1);
console.group('===== 取得一個使用者的狀態 =====');
console.log(singleUser);
console.groupEnd();

// 取得多筆使用者

const stmtMultiple = db.prepare(`
  SELECT * FROM users
`);

const userList = stmtMultiple.all();

console.group('====== 取得多比使用者的狀況 =====');
console.log(userList);
console.groupEnd();

result

原子性 (atomicity)

講到資料庫肯定要講到 ACID 當然因為我們的主軸在 bun
所以針對資料庫的部分不會著墨太多,我們這裡就講 transaction
的部分,確保原子性,bun 在這裡就有提供 transaction 的方法確保 atomicity

我們這裡示範一下,

import { Database } from 'bun:sqlite';

const db = new Database();

db.run(`
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT NOT NULL
  )
`)

interface User {
  name: string
  email: string
}

const batchInsertMany = db.transaction<[users: User[]], void>((users) => {
  const insert = db.prepare(`
    INSERT INTO users (name, email) VALUES (?, ?)
  `)
  for (const user of users) {
    insert.run(user.name, user.email);
  }
});

batchInsertMany([
  { name: 'Michael', email: 'Michael@gmail.com' },
  { name: 'Mike', email: 'Mike@gmail.com' },
  { name: 'Nick', email: 'Nick@gmail.com' },
  { name: 'Nick', email: 'Nick@gmail.com' },
  { name: 'Boss', email: 'boss@gmail.com' },
]);

console.log('===== 這裡看看結果 =====');
const query = db.prepare(`SELECT * FROM users`);
console.log(query.all());

batch_result

結論

相較於 Node.js 直到 v26.5.0 才推出官方的 sqlite 模組,
Bun 在這方面確實走得更早、更完整,也再次展現了 Bun 在「開箱即用」這個定位上的野心。
如果你的專案不需要太複雜的資料庫功能,bun:sqlite 會是一個相當輕量、且效能優異的選擇,
非常適合用在小型服務、原型開發,或是測試環境的建置上。


上一篇
Bun File I/O:讀寫檔案與 AWS s3 完美整合
系列文
不只是快 —— Bun 30 天:從底層架構、全套工具鏈到生產部署11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言