C++链接并操作嵌入式数据库SQLite
1. 简单介绍SQLite是一个以C语言库形式发布的嵌入式数据库引擎。在C项目中使用它主要有两种方式直接使用C API这是最直接、最底层的方式。SQLite本身提供一个纯C语言编写的头文件sqlite3.h和库文件如sqlite3.lib,sqlite3.dll或libsqlite3.a,libsqlite3.so。步骤获取库文件从SQLite官网下载预编译的二进制文件或下载源码自行编译。配置项目在项目中包含sqlite3.h头文件。在链接器设置中添加SQLite的库文件路径并链接sqlite3库。代码中调用在C代码中可以直接调用SQLite的C API函数如sqlite3_open(),sqlite3_exec(),sqlite3_prepare_v2()等。由于C兼容C这种方式是原生支持的。使用C封装库为了获得更符合C编程习惯如RAII、异常安全、面向对象的接口社区创建了许多C封装库。一个流行且轻量级的选择是SQLiteCpp。它包装了原始C API提供了更现代、更安全的C接口。步骤获取库通过包管理器如vcpkg, conan安装或从GitHub获取源码。包含头文件包含SQLiteCpp.h。使用C风格接口使用SQLite::Database,SQLite::Statement等类进行操作代码更简洁资源管理更安全。2. 基本操作流程C 操作 SQLite 通常需要以下步骤1. 链接 SQLite 库静态链接// 直接包含 sqlite3.c 源文件到项目中 #include sqlite3.c // 编译时g main.cpp -o app -lpthread -ldl动态链接// 使用头文件和动态库 #include sqlite3.h // 编译时g main.cpp -o app -lsqlite3 -lpthread -ldl各参数说明gC 编译器main.cpp你的源代码文件-o app指定输出可执行文件名为app-lsqlite3链接 SQLite3 库-lpthread链接 POSIX 线程库-ldl链接动态加载库Linux 上需要2. 示例#include sqlite3.h #include iostream #include string class SQLiteDB { private: sqlite3* db; public: SQLiteDB() : db(nullptr) {} // 打开数据库 bool open(const std::string filename) { int rc sqlite3_open(filename.c_str(), db); if (rc ! SQLITE_OK) { std::cerr 无法打开数据库: sqlite3_errmsg(db) std::endl; return false; } return true; } // 执行 SQL 语句 bool execute(const std::string sql) { char* errMsg nullptr; int rc sqlite3_exec(db, sql.c_str(), nullptr, nullptr, errMsg); if (rc ! SQLITE_OK) { std::cerr SQL 错误: errMsg std::endl; sqlite3_free(errMsg); return false; } return true; } // 查询数据回调函数方式 static int callback(void* data, int argc, char** argv, char** colName) { for (int i 0; i argc; i) { std::cout colName[i] (argv[i] ? argv[i] : NULL) std::endl; } std::cout -------- std::endl; return 0; } // 带参数的查询 bool query(const std::string sql) { char* errMsg nullptr; int rc sqlite3_exec(db, sql.c_str(), callback, nullptr, errMsg); if (rc ! SQLITE_OK) { std::cerr 查询错误: errMsg std::endl; sqlite3_free(errMsg); return false; } return true; } // 使用预处理语句防SQL注入 bool preparedInsert(const std::string name, int age) { sqlite3_stmt* stmt; const char* sql INSERT INTO users (name, age) VALUES (?, ?); int rc sqlite3_prepare_v2(db, sql, -1, stmt, nullptr); if (rc ! SQLITE_OK) { return false; } // 绑定参数 sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_STATIC); sqlite3_bind_int(stmt, 2, age); // 执行 rc sqlite3_step(stmt); // 清理 sqlite3_finalize(stmt); return rc SQLITE_DONE; } // 关闭数据库 void close() { if (db) { sqlite3_close(db); db nullptr; } } ~SQLiteDB() { close(); } }; int main() { SQLiteDB database; // 打开数据库如果不存在则创建 if (!database.open(test.db)) { return 1; } // 创建表 database.execute(CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)); // 插入数据 database.execute(INSERT INTO users (name, age) VALUES (张三, 25)); database.execute(INSERT INTO users (name, age) VALUES (李四, 30)); // 使用预处理语句插入 database.preparedInsert(王五, 28); // 查询数据 std::cout 查询结果 std::endl; database.query(SELECT * FROM users); // 更新数据 database.execute(UPDATE users SET age 26 WHERE name 张三); // 删除数据 database.execute(DELETE FROM users WHERE age 29); // 再次查询 std::cout \n更新后的结果 std::endl; database.query(SELECT * FROM users); return 0; }3. 使用 C 封装库简化复杂操作除了直接使用 C API还可以使用 C 封装库SQLiteCpp推荐#include SQLiteCpp/SQLiteCpp.h #include iostream int main() { try { // 打开数据库 SQLite::Database db(test.db, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE); // 执行 SQL db.exec(CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)); // 插入数据 SQLite::Statement insert(db, INSERT INTO users (name, age) VALUES (?, ?)); insert.bind(1, 张三); insert.bind(2, 25); insert.exec(); // 查询数据 SQLite::Statement query(db, SELECT * FROM users); while (query.executeStep()) { int id query.getColumn(0); std::string name query.getColumn(1); int age query.getColumn(2); std::cout id: id , name: name , age: age std::endl; } } catch (std::exception e) { std::cerr SQLite 异常: e.what() std::endl; } return 0; }4. 编译命令直接编译# 使用系统库 g main.cpp -o app -lsqlite3 -lpthread -ldl # 使用 SQLiteCpp g main.cpp -o app -lsqlite3 -lSQLiteCpp -lpthread -ldlCMake 配置cmake_minimum_required(VERSION 3.10) project(SQLiteExample) find_package(SQLite3 REQUIRED) find_package(SQLiteCpp REQUIRED) # 如果使用 SQLiteCpp add_executable(app main.cpp) target_link_libraries(app SQLite::SQLite3) target_link_libraries(app SQLiteCpp) # 如果使用 SQLiteCpp5. 主要特点零配置无需服务器单文件数据库事务支持ACID 兼容跨平台支持 Windows、Linux、macOS 等轻量级库文件小资源占用少丰富的 API提供完整的 SQL 支持SQL Structured Query Language结构化查询语言6.与其他数据库的扩展名对比数据库系统常见扩展名说明SQLite.db,.sqlite,.sqlite3单文件嵌入式数据库MySQL.sql,.frm,.ibd需要服务器多文件PostgreSQL无特定扩展名目录结构无单文件SQL Server.mdf,.ldf微软数据库系统Oracle.dbf,.ora企业级数据库SQLite (加密).db,.sqlite内容加密扩展名相同Access.mdb,.accdb微软 Access 数据库