SQLite的c++接口
安装
这里建议使用msys2进行安装,如果你使用的是vs编译c++程序也可以使用vcpkg进行安装。
C/C++ 接口 API
SQLite的C/C++接口提供了一系列的函数,可以用来操作数据库,包括创建数据库,创建表,插入数据,查询数据,更新数据,删除数据等。
实例
众所周知学习一个编程语言的最好方式就是通过实例来学习,下面我们就用C++来实现一个简单的数据库操作。
c++
#include <iostream>
#include <sqlite3.h> // SQLite头文件
#include <string>
// 数据库文件名
const char* DB_NAME = "test.db";
// 创建表格SQL语句
const char* CREATE_TABLE_SQL =
"CREATE TABLE IF NOT EXISTS users ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"name TEXT NOT NULL,"
"age INTEGER,"
"email TEXT);";
// 数据库连接句柄
sqlite3* db = nullptr;
// 连接数据库
bool connectDatabase() {
int rc = sqlite3_open(DB_NAME, &db);
if (rc != SQLITE_OK) {
std::cerr << "无法打开数据库: " << sqlite3_errmsg(db) << std::endl;
return false;
}
std::cout << "数据库连接成功!" << std::endl;
return true;
}
// 关闭数据库连接
void disconnectDatabase() {
if (db) {
sqlite3_close(db);
std::cout << "数据库连接已关闭" << std::endl;
}
}
// 创建表格
bool createTable() {
char* errMsg = nullptr;
int rc = sqlite3_exec(db, CREATE_TABLE_SQL, nullptr, nullptr, &errMsg);
if (rc != SQLITE_OK) {
std::cerr << "创建表格失败: " << errMsg << std::endl;
sqlite3_free(errMsg);
return false;
}
std::cout << "表格创建/检测成功" << std::endl;
return true;
}
// 插入数据
bool insertUser(const std::string& name, int age, const std::string& email) {
const char* sql = "INSERT INTO users (name, age, email) VALUES (?, ?, ?);";
sqlite3_stmt* stmt;
// 准备预处理语句
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
if (rc != SQLITE_OK) {
std::cerr << "准备插入语句失败: " << sqlite3_errmsg(db) << std::endl;
return false;
}
// 绑定参数
sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_int(stmt, 2, age);
sqlite3_bind_text(stmt, 3, email.c_str(), -1, SQLITE_STATIC);
// 执行语句
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {
std::cerr << "执行插入失败: " << sqlite3_errmsg(db) << std::endl;
sqlite3_finalize(stmt);
return false;
}
std::cout << "插入数据成功,ID: " << sqlite3_last_insert_rowid(db) << std::endl;
sqlite3_finalize(stmt);
return true;
}
// 查询数据回调函数
static int selectCallback(void* data, 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 << "\n";
return 0;
}
// 查询所有用户
void selectAllUsers() {
const char* sql = "SELECT * FROM users;";
char* errMsg = nullptr;
std::cout << "\n查询结果:" << std::endl;
int rc = sqlite3_exec(db, sql, selectCallback, nullptr, &errMsg);
if (rc != SQLITE_OK) {
std::cerr << "查询失败: " << errMsg << std::endl;
sqlite3_free(errMsg);
}
}
// 更新用户信息
bool updateUser(int id, const std::string& newEmail) {
const char* sql = "UPDATE users SET email = ? WHERE id = ?;";
sqlite3_stmt* stmt;
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
if (rc != SQLITE_OK) {
std::cerr << "准备更新语句失败: " << sqlite3_errmsg(db) << std::endl;
return false;
}
sqlite3_bind_text(stmt, 1, newEmail.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_int(stmt, 2, id);
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {
std::cerr << "执行更新失败: " << sqlite3_errmsg(db) << std::endl;
sqlite3_finalize(stmt);
return false;
}
std::cout << "更新影响行数: " << sqlite3_changes(db) << std::endl;
sqlite3_finalize(stmt);
return true;
}
// 删除用户
bool deleteUser(int id) {
const char* sql = "DELETE FROM users WHERE id = ?;";
sqlite3_stmt* stmt;
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
if (rc != SQLITE_OK) {
std::cerr << "准备删除语句失败: " << sqlite3_errmsg(db) << std::endl;
return false;
}
sqlite3_bind_int(stmt, 1, id);
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {
std::cerr << "执行删除失败: " << sqlite3_errmsg(db) << std::endl;
sqlite3_finalize(stmt);
return false;
}
std::cout << "删除影响行数: " << sqlite3_changes(db) << std::endl;
sqlite3_finalize(stmt);
return true;
}
int main() {
// 连接数据库
if (!connectDatabase()) return 1;
// 创建表格
if (!createTable()) {
disconnectDatabase();
return 1;
}
// 插入示例数据
insertUser("张三", 25, "zhangsan@example.com");
insertUser("李四", 30, "lisi@example.com");
// 查询所有数据
selectAllUsers();
// 更新数据(假设第一条记录的ID是1)
updateUser(1, "new_email@example.com");
selectAllUsers();
// 删除数据(假设要删除ID为2的记录)
deleteUser(2);
selectAllUsers();
// 关闭数据库连接
disconnectDatabase();
return 0;
}
这很长对吧但是我们可以逐一击破
讲解实例
这段代码是一个使用 SQLite 数据库的 C++ 程序,主要功能包括连接数据库、创建表格、插入数据、查询数据、更新数据和删除数据。以下是对代码的详细解析:
1. 头文件与全局变量
cpp
#include <iostream>
#include <sqlite3.h> // SQLite头文件
#include <string>
// 数据库文件名
const char* DB_NAME = "test.db";
// 创建表格SQL语句
const char* CREATE_TABLE_SQL =
"CREATE TABLE IF NOT EXISTS users ("
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
"name TEXT NOT NULL,"
"age INTEGER,"
"email TEXT);";
// 数据库连接句柄
sqlite3* db = nullptr;
sqlite3.h
:SQLite 的头文件,提供了操作 SQLite 数据库的 API。DB_NAME
:数据库文件名,这里定义为test.db
。CREATE_TABLE_SQL
:创建表格的 SQL 语句,定义了一个名为users
的表格,包含id
、name
、age
和email
四个字段。sqlite3* db
:数据库连接句柄,用于存储数据库连接对象。
2. 连接与关闭数据库
cpp
bool connectDatabase() {
int rc = sqlite3_open(DB_NAME, &db);
if (rc != SQLITE_OK) {
std::cerr << "无法打开数据库: " << sqlite3_errmsg(db) << std::endl;
return false;
}
std::cout << "数据库连接成功!" << std::endl;
return true;
}
void disconnectDatabase() {
if (db) {
sqlite3_close(db);
std::cout << "数据库连接已关闭" << std::endl;
}
}
connectDatabase()
:连接数据库,使用sqlite3_open
打开数据库文件。如果成功,返回true
;否则输出错误信息并返回false
。disconnectDatabase()
:关闭数据库连接,使用sqlite3_close
释放资源。
3. 创建表格
cpp
bool createTable() {
char* errMsg = nullptr;
int rc = sqlite3_exec(db, CREATE_TABLE_SQL, nullptr, nullptr, &errMsg);
if (rc != SQLITE_OK) {
std::cerr << "创建表格失败: " << errMsg << std::endl;
sqlite3_free(errMsg);
return false;
}
std::cout << "表格创建/检测成功" << std::endl;
return true;
}
createTable()
:执行 SQL 语句创建表格。如果表格已存在,则不会重复创建。sqlite3_exec()
:执行 SQL 语句的函数。如果执行失败,会通过errMsg
返回错误信息。
4. 插入数据
cpp
bool insertUser(const std::string& name, int age, const std::string& email) {
const char* sql = "INSERT INTO users (name, age, email) VALUES (?, ?, ?);";
sqlite3_stmt* stmt;
// 准备预处理语句
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
if (rc != SQLITE_OK) {
std::cerr << "准备插入语句失败: " << sqlite3_errmsg(db) << std::endl;
return false;
}
// 绑定参数
sqlite3_bind_text(stmt, 1, name.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_int(stmt, 2, age);
sqlite3_bind_text(stmt, 3, email.c_str(), -1, SQLITE_STATIC);
// 执行语句
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {
std::cerr << "执行插入失败: " << sqlite3_errmsg(db) << std::endl;
sqlite3_finalize(stmt);
return false;
}
std::cout << "插入数据成功,ID: " << sqlite3_last_insert_rowid(db) << std::endl;
sqlite3_finalize(stmt);
return true;
}
insertUser()
:插入一条用户数据。sqlite3_prepare_v2()
:准备 SQL 语句,返回一个sqlite3_stmt
对象。sqlite3_bind_*()
:绑定参数到预处理语句中。sqlite3_step()
:执行预处理语句。sqlite3_last_insert_rowid()
:获取最后插入行的 ID。
5. 查询数据
cpp
static int selectCallback(void* data, 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 << "\n";
return 0;
}
void selectAllUsers() {
const char* sql = "SELECT * FROM users;";
char* errMsg = nullptr;
std::cout << "\n查询结果:" << std::endl;
int rc = sqlite3_exec(db, sql, selectCallback, nullptr, &errMsg);
if (rc != SQLITE_OK) {
std::cerr << "查询失败: " << errMsg << std::endl;
sqlite3_free(errMsg);
}
}
selectCallback()
:查询结果的回调函数,用于逐行处理查询结果。selectAllUsers()
:查询所有用户数据,使用sqlite3_exec
执行查询,并通过回调函数输出结果。
6. 更新数据
cpp
bool updateUser(int id, const std::string& newEmail) {
const char* sql = "UPDATE users SET email = ? WHERE id = ?;";
sqlite3_stmt* stmt;
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
if (rc != SQLITE_OK) {
std::cerr << "准备更新语句失败: " << sqlite3_errmsg(db) << std::endl;
return false;
}
sqlite3_bind_text(stmt, 1, newEmail.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_int(stmt, 2, id);
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {
std::cerr << "执行更新失败: " << sqlite3_errmsg(db) << std::endl;
sqlite3_finalize(stmt);
return false;
}
std::cout << "更新影响行数: " << sqlite3_changes(db) << std::endl;
sqlite3_finalize(stmt);
return true;
}
updateUser()
:更新指定用户的邮箱。sqlite3_changes()
:返回受更新操作影响的行数。
7. 删除数据
cpp
bool deleteUser(int id) {
const char* sql = "DELETE FROM users WHERE id = ?;";
sqlite3_stmt* stmt;
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
if (rc != SQLITE_OK) {
std::cerr << "准备删除语句失败: " << sqlite3_errmsg(db) << std::endl;
return false;
}
sqlite3_bind_int(stmt, 1, id);
rc = sqlite3_step(stmt);
if (rc != SQLITE_DONE) {
std::cerr << "执行删除失败: " << sqlite3_errmsg(db) << std::endl;
sqlite3_finalize(stmt);
return false;
}
std::cout << "删除影响行数: " << sqlite3_changes(db) << std::endl;
sqlite3_finalize(stmt);
return true;
}
deleteUser()
:删除指定 ID 的用户。
8. 主函数
cpp
int main() {
// 连接数据库
if (!connectDatabase()) return 1;
// 创建表格
if (!createTable()) {
disconnectDatabase();
return 1;
}
// 插入示例数据
insertUser("张三", 25, "zhangsan@example.com");
insertUser("李四", 30, "lisi@example.com");
// 查询所有数据
selectAllUsers();
// 更新数据(假设第一条记录的ID是1)
updateUser(1, "new_email@example.com");
selectAllUsers();
// 删除数据(假设要删除ID为2的记录)
deleteUser(2);
selectAllUsers();
// 关闭数据库连接
disconnectDatabase();
return 0;
}
main()
:程序的入口函数,依次执行连接数据库、创建表格、插入数据、查询数据、更新数据和删除数据等操作。
9. 总结
- 这段代码展示了如何使用 SQLite 数据库进行基本的 CRUD(增删改查)操作。
- 使用了预处理语句(
sqlite3_prepare_v2
)来防止 SQL 注入。 - 通过回调函数处理查询结果。
- 代码结构清晰,适合初学者学习 SQLite 的基本用法。
函数列表
以下是 SQLite3 中核心函数的分类和通俗讲解,帮助你快速理解它们的用途和使用场景。(由于 SQLite3 函数库庞大,这里列举常用核心函数)
一、数据库连接与关闭
1. sqlite3_open()
- 作用:打开一个数据库文件,建立连接。
- 参数:
- 数据库文件名(如
"test.db"
)。 - 指向
sqlite3*
的指针,用于保存连接句柄。
- 数据库文件名(如
- 示例:cpp
sqlite3* db; int rc = sqlite3_open("test.db", &db); // 打开数据库 if (rc != SQLITE_OK) { std::cerr << "打开失败!"; }
2. sqlite3_close()
- 作用:关闭数据库连接,释放资源。
- 参数:
sqlite3*
连接句柄。 - 示例:cpp
sqlite3_close(db); // 关闭连接
二、执行 SQL 语句
1. sqlite3_exec()
- 作用:直接执行 SQL 语句(适合简单操作,如建表、插入)。
- 参数:
- SQL 语句字符串。
- 回调函数(处理查询结果)。
- 回调函数的参数。
- 错误信息指针。
- 示例:cpp
const char* sql = "CREATE TABLE users (id INTEGER, name TEXT);"; char* errmsg; int rc = sqlite3_exec(db, sql, nullptr, nullptr, &errmsg); if (rc != SQLITE_OK) { std::cerr << "错误: " << errmsg; sqlite3_free(errmsg); }
2. sqlite3_prepare_v2()
- 作用:将 SQL 语句编译为预处理语句(防止 SQL 注入,适合复杂操作)。
- 参数:
- SQL 语句字符串。
- 输出预处理语句句柄
sqlite3_stmt**
。
- 示例:cpp
const char* sql = "SELECT * FROM users WHERE id = ?;"; sqlite3_stmt* stmt; int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
3. sqlite3_step()
- 作用:执行预处理语句,并逐行获取结果。
- 返回值:
SQLITE_ROW
:表示有数据行可用。SQLITE_DONE
:表示执行完成(如插入、更新操作)。
- 示例:cpp
while (sqlite3_step(stmt) == SQLITE_ROW) { // 读取数据 int id = sqlite3_column_int(stmt, 0); }
4. sqlite3_finalize()
- 作用:释放预处理语句占用的资源。
- 示例:cpp
sqlite3_finalize(stmt); // 释放预处理语句
三、参数绑定与数据读取
1. 绑定参数函数
- 作用:向预处理语句中的占位符
?
绑定具体值。 - 常用函数:
sqlite3_bind_int(stmt, 位置, 值)
sqlite3_bind_text(stmt, 位置, 字符串, 长度, 释放方式)
- 示例:cpp
sqlite3_bind_int(stmt, 1, 100); // 绑定 id=100 sqlite3_bind_text(stmt, 2, "Alice", -1, SQLITE_STATIC);
2. 读取结果函数
- 作用:从查询结果的当前行中读取数据。
- 常用函数:
sqlite3_column_int(stmt, 列索引)
sqlite3_column_text(stmt, 列索引)
- 示例:cpp
int id = sqlite3_column_int(stmt, 0); // 读取第1列(整数) const char* name = (const char*)sqlite3_column_text(stmt, 1); // 读取第2列(字符串)
四、实用工具函数
1. sqlite3_last_insert_rowid()
- 作用:获取最后插入行的自增 ID。
- 示例:cpp
int lastId = sqlite3_last_insert_rowid(db);
2. sqlite3_changes()
- 作用:返回最近一次操作(如更新、删除)影响的行数。
- 示例:cpp
int rows = sqlite3_changes(db); // 更新/删除了多少行
3. sqlite3_errmsg()
- 作用:获取最近一次错误的描述信息。
- 示例:cpp
std::cerr << "错误: " << sqlite3_errmsg(db);
五、事务控制
1. BEGIN TRANSACTION
和 COMMIT
- 作用:手动控制事务(SQL 语句,非直接函数)。
- 示例:cpp
sqlite3_exec(db, "BEGIN TRANSACTION;", nullptr, nullptr, nullptr); // 执行多个操作... sqlite3_exec(db, "COMMIT;", nullptr, nullptr, nullptr);
六、总结
核心函数使用场景
场景 | 使用的函数 |
---|---|
打开/关闭数据库 | sqlite3_open() , sqlite3_close() |
执行简单 SQL 语句 | sqlite3_exec() |
执行复杂/安全 SQL 语句 | sqlite3_prepare_v2() , sqlite3_step() |
绑定参数 | sqlite3_bind_*() |
读取结果 | sqlite3_column_*() |
错误处理 | sqlite3_errmsg() |
通俗理解
- 预处理语句:像一个填空题模板,先写好 SQL 语句框架(如
SELECT * FROM users WHERE id = ?
),再用sqlite3_bind_*()
填入具体值,安全高效。 - 回调函数:适合简单的查询,每次读到一行数据就自动调用回调函数处理。
- 事务:把多个操作打包,要么全部成功,要么全部失败(比如转账操作)。