專案需本地持久化結構化數據,字段較多且需靈活查詢。記憶體結構(vector/map)查詢不便,重型資料庫(MySQL/PostgreSQL)部署過於繁瑣。SQLite 作為零配置、單文件、跨平台的嵌入式引擎,完美契合輕量級本地存儲場景。
SELECT 結果集。
#ifndef SQLITE_HELPER_H
#define SQLITE_HELPER_H
#include <sqlite3.h>
#include <string>
class SQLiteHelper {
public:
SQLiteHelper() : db_(nullptr), errMsg_(nullptr), isClosed_(true) {}
~SQLiteHelper() { close(); }
// 禁止拷貝,支援移動
SQLiteHelper(const SQLiteHelper&) = delete;
SQLiteHelper& operator=(const SQLiteHelper&) = delete;
SQLiteHelper(SQLiteHelper&& other) noexcept
: db_(other.db_), errMsg_(other.errMsg_), isClosed_(other.isClosed_) {
other.db_ = nullptr; other.errMsg_ = nullptr; other.isClosed_ = true;
}
// 核心操作
bool open(const std::string& path);
void close();
bool exec(const std::string& sql); // 通用執行(DDL/DML)
bool query(const std::string& sql); // 查詢並觸發回調顯示
bool beginTransaction();
bool commitTransaction();
bool rollbackTransaction();
// 便利方法
bool createTable(const std::string& tableDef);
bool dropTable(const std::string& tableName);
bool insert(const std::string& sql);
bool update(const std::string& sql);
bool remove(const std::string& sql);
private:
sqlite3* db_;
char* errMsg_;
bool isClosed_;
static int callback(void* notUsed, int argc, char** argv, char** colName);
bool execInternal(const char* sql);
};
#endif
bool SQLiteHelper::open(const std::string& path) {
if (!isClosed_) close();
int rc = sqlite3_open(path.c_str(), &db_);
if (rc != SQLITE_OK) {
std::cerr << "Open DB failed: " << sqlite3_errmsg(db_) << std::endl;
sqlite3_close(db_);
db_ = nullptr;
return false;
}
isClosed_ = false;
return true;
}
void SQLiteHelper::close() {
if (!isClosed_ && db_) {
sqlite3_close(db_);
db_ = nullptr;
isClosed_ = true;
}
}
bool SQLiteHelper::insert(const std::string& sql) {
if (!beginTransaction()) return false;
bool ok = execInternal(sql.c_str());
if (ok) ok = commitTransaction();
else rollbackTransaction();
return ok;
}
bool SQLiteHelper::beginTransaction() {
return execInternal("BEGIN TRANSACTION;");
}
bool SQLiteHelper::commitTransaction() {
return execInternal("COMMIT TRANSACTION;");
}
bool SQLiteHelper::rollbackTransaction() {
return execInternal("ROLLBACK TRANSACTION;");
}
int SQLiteHelper::callback(void* notUsed, int argc, char** argv, char** colName) {
for (int i = 0; i < argc; ++i) {
std::cout << colName[i] << " = " << (argv[i] ? argv[i] : "NULL") << "\t";
}
std::cout << std::endl;
return 0; // 返回非 0 會中止查詢
}
bool SQLiteHelper::query(const std::string& sql) {
return execInternal(sql.c_str());
}
bool SQLiteHelper::execInternal(const char* sql) {
char* errMsg = nullptr;
int rc = sqlite3_exec(db_, sql, callback, nullptr, &errMsg);
if (rc != SQLITE_OK) {
std::cerr << "SQL Error: " << (errMsg ? errMsg : "Unknown") << std::endl;
sqlite3_free(errMsg);
return false;
}
return true;
}
#include "sqlite_helper.h"
#include <iostream>
#include <sstream>
int main() {
SQLiteHelper db;
if (!db.open("./Test.db3")) return 1;
// 建表
if (!db.createTable("test_table (id INT PRIMARY KEY, name TEXT, age INT)")) return 1;
// 批量插入(事務保護)
for (int i = 1; i < 10; ++i) {
std::ostringstream oss;
oss << "INSERT INTO test_table VALUES (" << i << ", 'Name" << i+10 << "', 23);";
if (!db.insert(oss.str())) return 1;
}
db.query("SELECT * FROM test_table;");
// 刪除
db.remove("DELETE FROM test_table WHERE id = 4;");
db.query("SELECT * FROM test_table;");
// 更新
db.update("UPDATE test_table SET name = 'SQLite3' WHERE name = '17';");
db.query("SELECT * FROM test_table;");
// 刪表
db.dropTable("test_table");
db.query("SELECT * FROM test_table;"); // 將報錯:no such table
return 0;
}
sqlite3_prepare_v2 + sqlite3_bind,防注入並提速。PRAGMA journal_mode=WAL; 大幅提升並發讀寫效能。queryParams(sql, params...) 介面,自動綁定參數。TEXT 列可存數字,應用層需自行驗證。sqlite3_exec 回調函數中不可再呼叫 sqlite3_exec,會死鎖。sqlite3_busy_timeout。