SQLite 完整教學 2026:地表最普及的資料庫,從安裝、JSONB、FTS5 全文搜尋到 Python 實戰一次學會

SQLite 是全球部署最廣泛的資料庫:超過 1 兆個資料庫正在運行,每支手機、每個瀏覽器都有它。這篇完整教學帶你從安裝開始,學會 JSONB 二進位儲存、FTS5 全文搜尋、WAL 併發模式,以及 Python 實戰的最佳實踐,附可直接執行的程式碼。

  • Dennis
  • 7 分鐘閱讀
SQLite 完整教學 2026:地表最普及的資料庫,從安裝、JSONB、FTS5 全文搜尋到 Python 實戰一次學會

SQLite 是全世界部署最廣泛的資料庫引擎——超過 1 兆個資料庫正在運行,比所有其他資料庫加起來還多。它零設定、單一檔案、內建於 Python 標準庫,用一行 import sqlite3 就能開始。 這篇教學帶你從安裝、JSONB、FTS5 全文搜尋到 WAL 併發與 Python 最佳實踐一次學會。

為什麼 SQLite 無所不在?

先看幾個數字(來源:SQLite 官方統計):

  • 全球超過 40 億支智慧型手機,每支手機內建並運行數百個 SQLite 資料庫
  • 推估全球有超過 1 兆個(1e12)正在運行的 SQLite 資料庫
  • 是全球第二廣泛部署的軟體庫,僅次於壓縮庫 zlib

你每天用的東西幾乎都靠它:Android 與 iPhone 的系統儲存、Chrome/Firefox/Safari 的瀏覽器資料、Skype、iTunes、Dropbox 用戶端……連 Python 和 PHP 都直接把 SQLite 內建在標準庫裡。你在商店買到的每一台電視、機上盒、車載導航,裡面也都有 SQLite。

SQLite 是什麼?三個關鍵特性

SQLite 是一個嵌入式(embedded)、單一檔案、零設定的關聯式資料庫。白話說:

特性說明
嵌入式不是獨立的伺服器程式,而是「函式庫」,直接嵌進你的應用程式裡
單一檔案整個資料庫就是一個 .db 檔案,複製檔案 = 備份資料庫
零設定不用安裝、不用開 port、不用設帳號密碼,檔案一開就能用
flowchart LR
    A[你的應用程式] -->|直接呼叫<br/>不用網路| B[(app.db<br/>單一檔案)]
    B --> C[零設定<br/>不用伺服器]
    B --> D[SQL 標準相容<br/>ACID 交易]
    B --> E[內建於<br/>Python/PHP]

安裝與基本操作

SQLite 不需要「安裝」——Python 內建、Mac 內建、Linux 套件管理器也有。這裡示範 CLI 工具的用法:

# Linux / macOS
sudo apt install sqlite3      # Debian/Ubuntu
brew install sqlite3          # macOS

# 建立資料庫並進入互動模式
sqlite3 myapp.db

# 互動模式內的操作
CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT NOT NULL, age INTEGER);
INSERT INTO users (name, age) VALUES ('小明', 28);
SELECT * FROM users;
.headers on            # 顯示欄位名稱
.mode column           # 表格排版

最新版本是 3.53.1(2026 年 5 月 5 日發布),修復了影響 3.7.0–3.51.2 的 WAL-reset 資料損壞競態漏洞,並新增查詢結果格式化(QRF)、ALTER TABLE 直接增刪 NOT NULL/CHECK 約束等功能。建議所有專案都升級到 3.51.3 以上

SQLite vs DuckDB:該用哪一個?

很多人會問 SQLite 跟 DuckDB 的差別。一句話:要存應用程式狀態 → SQLite;要分析大量資料、查 Parquet → DuckDB。我們的另一篇文章有完整比較,這裡用表格快速帶過:

比較項目SQLiteDuckDB
定位嵌入式 OLTP(交易處理)嵌入式 OLAP(分析查詢)
典型用途應用程式儲存、App 資料資料分析、大查詢、Parquet
寫入能力強(支援併發寫入)弱(分析為主)
記憶體資料庫支援支援
適合情境使用者資料、設定、快取報表、ETL、資料科學

JSONB:把 JSON 存成二進位,讀取快 2–3 倍

SQLite 從 3.45 版(2024 年 1 月)開始支援 JSONB——把 JSON 從純文字(TEXT)轉成緊湊的二進位格式(BLOB)儲存。好處是查詢時不需要每次重新解析整個 JSON 字串,讀取密集的應用效能顯著提升,佔用空間也更小。

-- 宣告為 BLOB,用 jsonb() 函數寫入
CREATE TABLE events (
  id      INTEGER PRIMARY KEY,
  payload BLOB NOT NULL
);

INSERT INTO events (payload)
VALUES (jsonb('{"user": {"id": 42}, "action": "login"}'));

-- 查詢完全透明,直接用 json_extract()
SELECT json_extract(payload, '$.user.id') AS user_id
FROM events
WHERE json_extract(payload, '$.action') = 'login';

-- 針對 JSON 內部欄位建立索引,加速搜尋
CREATE INDEX idx_action ON events (json_extract(payload, '$.action'));

💡 什麼時候用 TEXT、什麼時候用 JSONB? 頻繁查詢 JSON 內部值 → 用 BLOB + jsonb();需要保留原始字串(例如加密簽章、審計日誌要留原始格式)→ 用 TEXT。

FTS5 全文搜尋:告別慢到哭的 LIKE

當資料量變大,LIKE '%關鍵字%' 因為無法用索引而全表掃描,效能直接崩潰。SQLite 內建的 FTS5 虛擬表維護反向索引,支援專業級全文檢索:

-- 建立 FTS5 虛擬表
CREATE VIRTUAL TABLE posts USING fts5(title, body);

INSERT INTO posts (title, body) VALUES
  ('SQLite full-text search', 'FTS5 is fast and built in.'),
  ('Indexes in SQLite', 'B-trees power most lookups in SQLite.');

-- 基本搜尋(大小寫無關)
SELECT title FROM posts WHERE posts MATCH 'sqlite';

-- AND / 精確片語 / 前綴 / NOT / 欄位限定
SELECT title FROM posts WHERE posts MATCH 'fts5 AND index';
SELECT title FROM posts WHERE posts MATCH '"full-text search"';
SELECT title FROM posts WHERE posts MATCH 'trig*';
SELECT title FROM posts WHERE posts MATCH 'index NOT trigger';
SELECT title FROM posts WHERE posts MATCH 'title:sqlite';

BM25 相關度排名:每筆結果都有一個隱藏 rank 欄位,分數越低代表相關度越高。也可以自訂欄位權重:

-- 依相關度排序(rank 越低越相關)
SELECT title, rank FROM posts WHERE posts MATCH 'sqlite' ORDER BY rank;

-- 標題權重 10、內文權重 1
SELECT title, bm25(posts, 10.0, 1.0) AS score
FROM posts WHERE posts MATCH 'sqlite' ORDER BY score;

避免重複儲存:用外部內容表(content='實體表名'),FTS 表不存文字本體,再用 Trigger 自動同步索引:

CREATE TABLE articles (id INTEGER PRIMARY KEY, title TEXT, body TEXT);
CREATE VIRTUAL TABLE articles_fts USING fts5(
    title, body, content='articles', content_rowid='id'
);
-- 之後建立 INSERT/UPDATE/DELETE 三個 trigger 同步(範例略)

WAL 模式:併發讀寫不卡關

SQLite 從 3.7.0 版(2010 年)支援 WAL(Write-Ahead Logging),把「先寫日誌再改主檔」反轉成「直接 append 到 -wal 檔,之後再 checkpoint 回主檔」:

  • 讀寫並行:寫入時讀取者照常讀,不再互相阻塞
  • 寫入更快:交易只需對 WAL 檔做一次順序寫入
  • fsync 次數大減:對磁碟 I/O 敏感的系統差異明顯
  • ⚠️ 不支援 NFS:所有連線必須在同一台主機
  • ⚠️ 注意 checkpoint starvation:持續不間斷的讀取者可能讓 WAL 檔無限增長

啟用方式一行搞定(永久生效,重開資料庫依然有效):

PRAGMA journal_mode = WAL;   -- 回傳 "wal" 即成功

Python 實戰:五個最佳實踐

Python 的 sqlite3 是標準庫,import sqlite3 即可用。以下是從官方文件與實務整理出的五個關鍵習慣:

1. 用 row_factory 讀取 dict 格式

import sqlite3

conn = sqlite3.connect('app.db', timeout=60.0)
conn.row_factory = sqlite3.Row   # 可以用 row['name'] 取值

# 不需要 cursor 物件,直接 conn.execute 並迭代(避免 fetchall 佔記憶體)
for row in conn.execute('SELECT id, email FROM users WHERE age > ?', (20,)):
    print(row['id'], row['email'])

2. 永遠用參數化查詢,杜絕 SQL 注入

# ❌ 錯誤示範:f-string 拼接 SQL,等著被注入
# conn.execute(f"SELECT * FROM users WHERE name = '{user_input}'")

# ✅ 正確示範:使用 ? 預留位置
conn.execute("SELECT * FROM users WHERE name = ?", (user_input,))

3. 大量寫入用 executemany

在迴圈裡重複 execute 是最常見的效能殺手。實測寫入 100 萬筆資料:

方法耗時
迴圈內逐筆 execute2.7 秒
executemany 批次寫入1.6 秒
data = ((i, f"user_{i}") for i in range(100000))
conn.executemany("INSERT INTO users (id, name) VALUES (?, ?)", data)

大規模匯入時延後建索引:先全部寫完再 CREATE INDEX,省去每次插入更新 B-tree 的開銷,效能可以差好幾倍。

4. 併發寫入用 BEGIN IMMEDIATE

SQLite 支援無限多個並行讀取,但同時只能有一個寫入者。預設的 DEFERRED 交易在「先讀後寫」的場景容易撞出 database is locked。解法是一開場就鎖

try:
    with conn:   # context manager:成功自動 commit、錯誤自動 rollback
        conn.execute("BEGIN IMMEDIATE")   # 一開始就取得寫入鎖
        exists = conn.execute("SELECT 1 FROM users WHERE id = ?", (1,)).fetchone()
        if not exists:
            conn.execute("INSERT INTO users (id, email) VALUES (?, ?)", (1, "info@example.com"))
except sqlite3.IntegrityError as e:
    print("交易失敗,已自動 rollback:", e)

5. 善用記憶體資料庫

暫時性資料(測試、快取、分析)用 sqlite3.connect(':memory:'),速度極快且不落磁碟。

什麼時候「不要」用 SQLite?

SQLite 不是萬能的,遇到這些情境請改用 PostgreSQL / MySQL:

  • 多伺服器架構:SQLite 不能跨機器連線(WAL 也不支援 NFS)
  • 高併發寫入:同時多個寫入者,或用戶端直接連資料庫的多人服務
  • 需要使用者權限管理:SQLite 沒有帳號/角色系統
  • 超大資料庫:超過數百 GB 且持續成長,管理會變吃力

結語

SQLite 是那種「平常不會想到,但其實無所不在」的技術。對個人專案、工具型應用、AI Agent 的記憶儲存來說,它往往是最務實的選擇:零部署成本、單一檔案好備份、效能對單機應用綽綽有餘。而 JSONB、FTS5、WAL 這三件現代功能,讓它足以撐起很多「以為要架資料庫伺服器」的需求。

延伸閱讀

資料來源

📬 訂閱 most.tw 電子報

每週精選 AI 工具教學與技術乾貨,直接送到你的信箱。免費、隨時可退訂。

💬 有問題想討論?加 LINE 聯絡我

歡迎透過 LINE 官方帳號直接留言,我會盡快回覆你的問題。

加入 LINE 好友