C++中使用SQLite3需调用C风格API并结合RAII管理资源;SQLite3无原生C++接口,但因轻量嵌入式特性适合本地应用;初始化通过sqlite3_open打开数据库连接。

在 C++ 中使用 SQLite3 进行增删改查,核心是调用其 C 风格的 API,配合 C++ 的资源管理(如 RAII)来避免内存泄漏和句柄未关闭。SQLite3 本身不提供原生 C++ 接口,但轻量、嵌入式、无需服务端的特点让它非常适合桌面工具、本地缓存或小型应用。
1. 初始化数据库连接与基本准备
SQLite3 使用 sqlite3* 指针表示数据库连接。需包含头文件并链接库:
- Windows 下:包含
sqlite3.h,链接sqlite3.lib(或直接把sqlite3.c加入工程) - Linux/macOS:用
g++ -o app app.cpp -lsqlite3
打开数据库示例:
C++sqlite3* db;
int rc = sqlite3_open("example.db", &db);
if (rc != SQLITE_OK) {
std::cerr << "无法打开数据库:" << sqlite3_errmsg(db) << std::endl;
return -1;
}
// 记得用完后调用 sqlite3_close(db)
2. 执行建表与插入(CREATE / INSERT)
用 sqlite3_exec() 可执行 DDL 和简单 DML;若需绑定参数防 SQL 注入或提升性能,推荐用 sqlite3_prepare_v2() + sqlite3_bind_*。
立即学习“C++免费学习笔记(深入)”;
建表示例:
C++const char* sql = "CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY, name TEXT, age INTEGER);";
char* errMsg;
if (sqlite3_exec(db, sql, nullptr, nullptr, &errMsg) != SQLITE_OK) {
std::cerr << "建表失败:" << errMsg << std::endl;
sqlite3_free(errMsg);
}
安全插入(带参数绑定):
Metafox 是一个企业内容管理系统,使用一个特别的模板系统,你可通过一些特定的设计和代码来轻松创建 Web 网站,内容存储在 SQL 关系数据库,通过 Web 进行管理,简单、快速而且高效。 Metafox 0.9.1 发布,该版本改用一种更棒的 URL 风格,实现了 RSS 源(可包含远端网站内容到 Metafox 段中),重定向老的访问密钥到新的密钥,增加 RotateAntispam 技
const char* insertSql = "INSERT INTO users(name, age) VALUES(?, ?);";
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(db, insertSql, -1, &stmt, nullptr) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, "Alice", -1, SQLITE_STATIC);
sqlite3_bind_int(stmt, 2, 28);
if (sqlite3_step(stmt) != SQLITE_DONE) {
std::cerr << "插入失败:" << sqlite3_errmsg(db) << std::endl;
}
sqlite3_finalize(stmt); // 必须释放语句对象
}
3. 查询数据(SELECT)并遍历结果
查询必须用预编译语句 + 回调或逐行获取。推荐后者(sqlite3_step()),控制更灵活:
const char* selectSql = "SELECT id, name, age FROM users WHERE age > ?;";
sqlite3_stmt* stmt;
if (sqlite3_prepare_v2(db, selectSql, -1, &stmt, nullptr) == SQLITE_OK) {
sqlite3_bind_int(stmt, 1, 18);
while (sqlite3_step(stmt) == SQLITE_ROW) {
int id = sqlite3_column_int(stmt, 0);
const char* name = reinterpret_cast(sqlite3_column_text(stmt, 1));
int age = sqlite3_column_int(stmt, 2);
std::cout << "ID:" << id << ", 姓名:" << (name ? name : "NULL")
<< ", 年龄:" << age << std::endl;
}
sqlite3_finalize(stmt);
}
注意:sqlite3_column_text() 返回的是 UTF-8 字符串指针,生命周期仅在当前 sqlite3_step() 调用期间有效,如需长期保存应拷贝。
4. 删除与更新(DELETE / UPDATE)
同样建议用参数化语句防止误操作和注入:
C++// 删除
const char* delSql = "DELETE FROM users WHERE name = ?;";
if (sqlite3_prepare_v2(db, delSql, -1, &stmt, nullptr) == SQLITE_OK) {
sqlite3_bind_text(stmt, 1, "Bob", -1, SQLITE_STATIC);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
// 更新
const char* updSql = "UPDATE users SET age = ? WHERE id = ?;";
if (sqlite3_prepare_v2(db, updSql, -1, &stmt, nullptr) == SQLITE_OK) {
sqlite3_bind_int(stmt, 1, 30);
sqlite3_bind_int(stmt, 2, 1);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
执行成功后,可用 sqlite3_changes(db) 获取影响行数。
实际项目中建议封装一个轻量类(如 Database、Statement),自动管理 sqlite3* 和 sqlite3_stmt* 的生命周期,避免裸指针和重复错误处理。SQLite3 官方文档清晰,API 稳定,掌握这几十行核心调用,就能支撑绝大多数本地数据操作需求。










