首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

VC++嵌入式數據庫SQLite完整應用指南:從建庫到C API實戰

     編輯:關於VC++

SQLite 是全球部署量最大的嵌入式資料庫:零配置、單檔案、ACID 事務、支援大部份 SQL-92、無伺服器進程。本文涵蓋:SQLite 核心特性、命令列工具操作、VC++ 專案整合(靜態庫建置)、C API 核心流程、參數化查詢、事務控制、錯誤處理、效能優化最佳實踐。

SQLite 核心特性速覽

  • 零配置:無安裝、無服務、無設定檔,單一 .db 檔案即資料庫
  • 跨平台:Windows/Linux/macOS/嵌入式/移動端 完全相容
  • ACID 事務:甚至掉電也能保證一致性(WAL 模式)
  • 型別系統:動態型別(NULL/INTEGER/REAL/TEXT/BLOB),欄位型別僅建議
  • SQL-92 子集:SELECT/INSERT/UPDATE/DELETE、JOIN、子查詢、VIEW、TRIGGER、INDEX
  • 並發:多讀單寫,WAL 模式支援讀寫並行
  • 體積:< 600KB(全功能),適合嵌入式/移動應用

命令列工具快速上手


# 1. 建立/開啟資料庫
sqlite3.exe mydb.db

# 2. 建表
CREATE TABLE users (
    userid  VARCHAR(20) PRIMARY KEY,
    age     INT,
    birthday DATETIME
);

# 3. 插入資料
INSERT INTO users VALUES ('wang', 20, '1989-05-04');
INSERT INTO users VALUES ('li', 22, '1987-11-16');

# 4. 查詢
SELECT * FROM users ORDER BY birthday;

# 5. 刪除
DELETE FROM users WHERE userid='wang';

# 6. 結構檢視
.schema users
.tables

# 7. 退出
.exit

元資料儲於 sqlite_master 表,可用 SELECT * FROM sqlite_master 檢視。

VC++ 專案整合:靜態庫建置

下載與準備

  • 官網 sqlite.org 下載:
    • sqlite-amalgamation-.zip(單檔源碼)
    • sqlitedll-.zip(預編譯 DLL + .def)
  • 建議:直接編譯 amalgamation 源碼為靜態庫,避免 DLL 部署麻煩

Visual Studio 2008+ 建置靜態庫


# 開啟 VS 命令提示字元
cd sqlite-amalgamation-3450100

# 直接編譯為 .lib
cl /c /O2 /DTHREADSAFE=1 /DSQLITE_THREADSAFE=1 sqlite3.c
lib /OUT:sqlite3.lib sqlite3.obj

# 或建立靜態庫專案:加入 sqlite3.c + sqlite3.h,配置 Release/Static Runtime

專案設定


// 標頭檔路徑
// C/C++ → General → Additional Include Directories: $(SolutionDir)sqlite\

// 連結庫
// Linker → General → Additional Library Directories: $(SolutionDir)sqlite\
// Linker → Input → Additional Dependencies: sqlite3.lib

// 代碼中
#include "sqlite3.h"
#pragma comment(lib, "sqlite3.lib")

C API 核心流程實戰

基本開啟/關閉


sqlite3* db = nullptr;
int rc = sqlite3_open("./test.db", &db); // 不存在則建立
if (rc != SQLITE_OK) {
    fprintf(stderr, "Open failed: %s\n", sqlite3_errmsg(db));
    return 1;
}
// ... 操作 ...
sqlite3_close(db);

回調函數處理查詢結果


static int Callback(void* notUsed, int argc, char** argv, char** colName) {
    for (int i = 0; i < argc; i++) {
        printf("%s = %s\n", colName[i], argv[i] ? argv[i] : "NULL");
    }
    printf("----\n");
    return 0; // 非零則中止查詢
}

完整範例:建表、插入、查詢


int main() {
    sqlite3* db = nullptr;
    char* errMsg = nullptr;
    int rc;
    
    // 開啟
    rc = sqlite3_open("./test.db", &db);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "Open error: %s\n", sqlite3_errmsg(db));
        return 1;
    }
    printf("Database opened!\n");
    
    // 執行多條 SQL(sqlite3_exec 內部自動事務)
    const char* sql = 
        "CREATE TABLE IF NOT EXISTS users("
        "  userid VARCHAR(20) PRIMARY KEY,"
        "  age INT,"
        "  birthday DATETIME"
        ");"
        "INSERT INTO users VALUES('wang', 20, '1989-05-04');"
        "INSERT INTO users VALUES('li', 22, '1987-11-16');"
        "SELECT * FROM users;";
    
    rc = sqlite3_exec(db, sql, Callback, 0, &errMsg);
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", errMsg);
        sqlite3_free(errMsg);
    }
    
    sqlite3_close(db);
    return 0;
}

進階用法:預處理語句

預處理語句 是高效能、防 SQL 注入、支援參數綁定的標準做法:


void PreparedStatementDemo(sqlite3* db) {
    const char* sql = "INSERT INTO users(userid, age, birthday) VALUES(?, ?, ?);";
    sqlite3_stmt* stmt = nullptr;
    
    // 1. 編譯 SQL
    int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
    if (rc != SQLITE_OK) { /* 錯誤處理 */ return; }
    
    // 2. 綁定參數並執行(可重複)
    for (int i = 1; i <= 100; i++) {
        char userid[20]; sprintf(userid, "user%d", i);
        
        sqlite3_bind_text(stmt, 1, userid, -1, SQLITE_TRANSIENT); // 參數1
        sqlite3_bind_int(stmt, 2, 20 + i % 50);                    // 參數2
        sqlite3_bind_text(stmt, 3, "2000-01-01", -1, SQLITE_STATIC); // 參數3
        
        rc = sqlite3_step(stmt);
        if (rc != SQLITE_DONE) { /* 錯誤 */ }
        
        sqlite3_reset(stmt); // 重置語句供下次使用
    }
    
    // 3. 釋放
    sqlite3_finalize(stmt);
}

參數綁定 API 速查

API用途記憶體管理
sqlite3_bind_text(stmt, idx, val, len, destructor)文字SQLITE_TRANSIENT複製、SQLITE_STATIC不複製
sqlite3_bind_int/stmt, idx, val)整數值複製
sqlite3_bind_double浮點值複製
sqlite3_bind_blob二進制同 text
sqlite3_bind_nullNULL值--
sqlite3_bind_zeroblob零填充BLOB--

事務控制


void TransactionDemo(sqlite3* db) {
    sqlite3_exec(db, "BEGIN TRANSACTION;", 0, 0, 0);
    // 或 BEGIN IMMEDIATE / BEGIN EXCLUSIVE
    
    bool success = true;
    for (int i=0; i<1000; i++) {
        if (ExecuteInsert(db, i) != SQLITE_DONE) { success = false; break; }
    }
    
    if (success) sqlite3_exec(db, "COMMIT;", 0, 0, 0);
    else         sqlite3_exec(db, "ROLLBACK;", 0, 0, 0);
}
  • BEGIN DEFERRED:預設,首次寫入才獲保留鎖
  • BEGIN IMMEDIATE:立即獲保留鎖,減少死鎖
  • BEGIN EXCLUSIVE:獨佔鎖,最高並發安全

效能優化最佳實踐

  1. 使用預處理語句 + 參數綁定:避免重複解析、防注入、批次插入極快
  2. 批次操作包裝在單一事務:1萬筆插入:無事務 ~30秒,有事務 ~0.3秒
  3. 啟用 WAL 模式:PRAGMA journal_mode=WAL; 讀寫並行、不阻塞讀取
  4. 適當索引:CREATE INDEX idx_age ON users(age);,但避免過度索引
  5. 連線複用:長連線避免重複開啟/關閉開銷
  6. 頁面大小調整:PRAGMA page_size=4096;(預設 4KB,大資料量可調 8K/16K/32K/64K)
  7. 同步模式:PRAGMA synchronous=NORMAL(平衡安全/速度),FULL 最安全,OFF 最快但掉電風險

常見錯誤碼與處理

適用場景與選型建議

錯誤碼常數含義處理
1SQLITE_ERROR通用錯誤檢查 errMsg
5SQLITE_BUSY資料庫被鎖設定 busy_timeout、重試、WAL模式
19SQLITE_CONSTRAINT約束違反(PK/UNIQUE/NOT NULL)檢查資料唯一性
21SQLITE_MISMATCH資料型別不匹配綁定參數型別正確
26SQLITE_LOCKED表被鎖避免長事務、檢查並發

總結

SQLite 以 「小而美」 重新定義嵌入式資料庫標準。VC++ 整合關鍵三步:

  1. 編譯 sqlite3.c 為靜態庫 sqlite3.lib
  2. 掌握 sqlite3_open → prepare_v2 → bind → step → reset → finalize → close 核心流程
  3. 善用 事務 + WAL + 預處理語句 三大效能殺手鐧

適用於 90% 的本地存儲場景;若遇高併發寫入、分布式、複雜分析查詢,請升級至 PostgreSQL/MySQL 等 Client-Server 架構資料庫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景推薦理由
桌面應用本地存儲✅ SQLite零部署、單檔、ACID
移動 App (iOS/Android)✅ SQLite系統內建、極致輕量
嵌入式裝置/物聯網✅ SQLite無服務、低資源、可靠
網站低中流量✅ SQLite簡單部署、足夠效能
高併發寫入/大數據量❌ PostgreSQL/MySQL需連接池、複雜查詢優化、分布式
多機器共享資料❌ Client-Server DBSQLite 無網路協議