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
动态链接
cpp
// 使用头文件和动态库
#include <sqlite3.h>
// 编译时:g++ main.cpp -o app -lsqlite3 -lpthread -ldl
各参数说明:
-
g++:C++ 编译器 -
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 -ldl
CMake 配置:
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) # 如果使用 SQLiteCpp
5. 主要特点
-
零配置:无需服务器,单文件数据库
-
事务支持: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 数据库 |