SQLite 官方提供「合併版」單文件源碼,極易集成:
# 下載最新版 (示例版本號) wget https://www.sqlite.org/2024/sqlite-amalgamation-3450100.zip unzip sqlite-amalgamation-3450100.zip cd sqlite-amalgamation-3450100 # 編譯為靜態庫 gcc -c -O2 -DSQLITE_THREADSAFE=1 -DSQLITE_ENABLE_FTS5=1 sqlite3.c -o sqlite3.o ar rcs libsqlite3.a sqlite3.o # 或直接編譯進項目 gcc -O2 main.c sqlite3.c -lpthread -ldl -o myapp
關鍵編譯宏:
| 宏 | 作用 | 推薦 |
|---|---|---|
SQLITE_THREADSAFE=1 | 啟用線程安全 (序列化模式) | ✅ 生產環境必開 |
SQLITE_DEFAULT_MEMSTATUS=0 | 關閉內存統計,微量提速 | 嵌入式設備 |
SQLITE_ENABLE_FTS5 | 全文搜索擴展 | 按需 |
SQLITE_MAX_MMAP_SIZE=0 | 禁用 mmap (某些嵌入式 FS 不支持) | 嵌入式 |
SQLITE_OMIT_DEPRECATED | 移除棄用 API,減小體積 | 精簡構建 |
sqlite3_open() → sqlite3_prepare_v2() → sqlite3_step() → sqlite3_column_*() → sqlite3_finalize() → sqlite3_close()
sqlite3 *db;
int rc = sqlite3_open("mydb.sqlite", &db); // 文件不存在則創建
if (rc != SQLITE_OK) {
fprintf(stderr, "Open failed: %s\n", sqlite3_errmsg(db));
return rc;
}
// 可選:啟用 WAL 模式提高併發
sqlite3_exec(db, "PRAGMA journal_mode=WAL;", NULL, NULL, NULL);
char *errmsg = NULL;
rc = sqlite3_exec(db,
"CREATE TABLE IF NOT EXISTS users ("
" id INTEGER PRIMARY KEY AUTOINCREMENT,"
" name TEXT NOT NULL,"
" email TEXT UNIQUE"
");",
NULL, NULL, &errmsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "Exec failed: %s\n", errmsg);
sqlite3_free(errmsg);
}
sqlite3_stmt *stmt;
const char *sql = "INSERT INTO users (name, email) VALUES (?, ?);";
rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) { /* handle error */ }
// 綁定參數
sqlite3_bind_text(stmt, 1, "Alice", -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, "alice@example.com", -1, SQLITE_TRANSIENT);
// 執行
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) { /* handle error */ }
sqlite3_reset(stmt); // 重置狀態,可重複綁定執行
// 批量插入示例
sqlite3_exec(db, "BEGIN TRANSACTION;", NULL, NULL, NULL);
for (int i = 0; i < 1000; ++i) {
char name[32], email[64];
sprintf(name, "User%d", i);
sprintf(email, "user%d@test.com", i);
sqlite3_bind_text(stmt, 1, name, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, email, -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
sqlite3_reset(stmt);
}
sqlite3_exec(db, "COMMIT;", NULL, NULL, NULL);
sqlite3_finalize(stmt); // 釋放預編譯語句資源
const char *qsql = "SELECT id, name, email FROM users WHERE id > ?;";
sqlite3_stmt *qstmt;
sqlite3_prepare_v2(db, qsql, -1, &qstmt, NULL);
sqlite3_bind_int(qstmt, 1, 10);
while ((rc = sqlite3_step(qstmt)) == SQLITE_ROW) {
int id = sqlite3_column_int(qstmt, 0);
const unsigned char *name = sqlite3_column_text(qstmt, 1);
const unsigned char *email = sqlite3_column_text(qstmt, 2);
printf("ID: %d, Name: %s, Email: %s\n", id, name, email);
}
if (rc != SQLITE_DONE) { /* error */ }
sqlite3_finalize(qstmt);
int callback(void *ctx, int argc, char **argv, char **colNames) {
for (int i = 0; i < argc; ++i)
printf("%s = %s\n", colNames[i], argv[i] ? argv[i] : "NULL");
puts("---");
return 0; // 非 0 終止查詢
}
sqlite3_exec(db, "SELECT * FROM users;", callback, NULL, &errmsg);
BEGIN; ... COMMIT;,否則極慢 (每次 fsync)。PRAGMA synchronous=NORMAL/OFF 可權衡安全與速度 (掉電風險)。sqlite3_exec(db, "PRAGMA journal_mode=WAL;", NULL, NULL, NULL); // 優點:讀寫不阻塞、崩潰恢復快、併發高 // 缺點:額外 -wal/-shm 文件、不支持網絡文件系統 (NFS/SMB)
sqlite3_open(":memory:", &db); // 純內存,進程結束消失
// 或共享內存數據庫
sqlite3_open("file::memory:?cache=shared", &db); // URI 格式,多連接共享
void my_upper(sqlite3_context *ctx, int argc, sqlite3_value **argv) {
const char *s = (const char *)sqlite3_value_text(argv[0]);
char *upper = strdup(s);
for (char *p = upper; *p; ++p) *p = toupper(*p);
sqlite3_result_text(ctx, upper, -1, free); // free 由 SQLite 調用釋放
}
sqlite3_create_function(db, "my_upper", 1, SQLITE_UTF8, NULL, my_upper, NULL, NULL);
// SQL 中使用: SELECT my_upper(name) FROM users;
#define SQLITE_CHECK(rc, db, label) \
do { if ((rc) != SQLITE_OK) { \
fprintf(stderr, "SQLite error %d at %s:%d: %s\n", \
rc, __FILE__, __LINE__, sqlite3_errmsg(db)); \
goto label; \
} } while(0)
int do_work() {
sqlite3 *db = NULL;
sqlite3_stmt *stmt = NULL;
int rc;
rc = sqlite3_open("app.db", &db);
SQLITE_CHECK(rc, db, err_db);
rc = sqlite3_prepare_v2(db, "SELECT 1", -1, &stmt, NULL);
SQLITE_CHECK(rc, db, err_stmt);
// ... use stmt ...
err_stmt:
sqlite3_finalize(stmt);
err_db:
sqlite3_close(db);
return rc;
}
cmake_minimum_required(VERSION 3.10)
project(MyApp)
# 方式 1: 系統庫
find_package(SQLite3 REQUIRED)
add_executable(myapp main.c)
target_link_libraries(myapp PRIVATE SQLite::SQLite3)
# 方式 2: 嵌入源碼 (推薦嵌入式/靜態鏈接)
add_library(sqlite3 STATIC third_party/sqlite3.c)
target_compile_definitions(sqlite3 PRIVATE
SQLITE_THREADSAFE=1
SQLITE_ENABLE_FTS5=1
)
add_executable(myapp main.c)
target_link_libraries(myapp PRIVATE sqlite3 pthread dl)
SQLite3 以零配置、單文件、ACID 事務、完整 SQL 支持、極小體積 成為嵌入式存儲王者。掌握參數化預編譯語句 (sqlite3_prepare_v2/bind/step/finalize)、顯式事務批量寫入、WAL 模式併發優化、錯誤碼檢查與資源 RAII 管理,即可在 C/C++ 項目中高效、安全地使用 SQLite。建議項目直接嵌入 sqlite3.c 靜態編譯,避免系統庫版本不匹配、編譯選項差異導致的隱性 Bug。