SQLiteDB 工具类使用说明
一、工具概述
本工具基于 SQLite3 C API 封装,支持 C++11+ 标准,提供轻量级、高易用性的 SQLite 数据库操作能力:
- 连接管理:数据库连接的创建 / 关闭全生命周期自动化,自动处理旧连接、空句柄等边界场景;
- SQL 执行 :
- 静态 SQL:支持无参数的建表、删表、批量插入等操作(封装
sqlite3_exec); - 预处理 SQL:支持带参数的增 / 删 / 改 / 查操作(封装
sqlite3_prepare_v2/sqlite3_bind_*/sqlite3_step),从根源避免 SQL 注入;
- 静态 SQL:支持无参数的建表、删表、批量插入等操作(封装
- 结果处理:查询结果自动封装为二维字符串数组,NULL 值统一转换为 "NULL" 字符串,无需手动解析底层数据结构;
- 健壮性:完善的参数校验、错误信息反馈、资源自动释放机制,避免内存泄漏、野指针、文件句柄泄漏等问题,降低程序崩溃风险。
二、前置准备步骤
1. 环境依赖
1.1 编译器要求
本工具类基于 C++11 标准开发,需确保编译器支持 C++11 及以上版本,推荐使用以下编译器版本(避免兼容性问题):
- Linux 系统:g++ 5.0 及以上、Clang 3.3 及以上;
- Mac 系统:Xcode 自带 Clang 编译器(版本 8.0 及以上);
- Windows 系统:Microsoft Visual Studio 2015 及以上(MSVC 14.0 及以上)。
若使用低于上述版本的编译器,可能会出现语法错误(如 std::vector 初始化方式、范围 for 循环、const 引用修饰等),建议升级编译器或修改代码以适配低版本标准(不推荐)。
1.2 库依赖说明
本工具类已集成 SQLite3 核心操作逻辑,仅需依赖 SQLite3 官方库(版本 3.7.0 及以上,推荐 3.30.0+),无需额外引入其他第三方库。不同操作系统的库安装和链接方式如下:
(1)Linux 系统(以 Ubuntu/Debian 为例)
-
安装 SQLite3 开发库(包含头文件和静态 / 动态库):
sudo apt update sudo apt install libsqlite3-dev -
验证安装是否成功:
sqlite3 --version # 查看 SQLite3 版本 ls /usr/include/sqlite3.h # 查看头文件是否存在 ls /usr/lib/x86_64-linux-gnu/libsqlite3.so # 查看动态库是否存在 -
编译时,需在编译命令中添加
-lsqlite3选项,链接 SQLite3 动态库,示例编译命令:g++ -std=c++11 -o test_sqlite test_sqlite.cpp SQLiteDB.cpp -lsqlite3
(2)Mac 系统
-
方式一:通过 Homebrew 安装(推荐):
brew install sqlite3 -
方式二:手动下载源码编译安装(适合需要指定版本的场景):
-
从 SQLite 官方网站(https://www.sqlite.org/download.html)下载源码包(如 sqlite-autoconf-3440000.tar.gz);
-
解压源码包,进入解压目录,执行以下命令编译安装:
./configure make sudo make install
-
-
编译时,同样需添加
-lsqlite3选项链接库文件,示例编译命令:g++ -std=c++11 -o test_sqlite test_sqlite.cpp SQLiteDB.cpp -lsqlite3
(3)Windows 系统
- 下载 SQLite3 库文件:
- 从 SQLite 官方网站下载适用于 Windows 的预编译库(包含头文件
sqlite3.h、静态库sqlite3.lib、动态库sqlite3.dll); - 推荐下载 "Precompiled Binaries for Windows" 中的 "sqlite-amalgamation-XXXXXXX.zip"(包含头文件和源码)和 "sqlite-dll-win64-x64-XXXXXXX.zip"(包含动态库)。
- 从 SQLite 官方网站下载适用于 Windows 的预编译库(包含头文件
- 项目配置(以 Visual Studio 2022 为例):
- 新建 C++ 项目,将
sqlite3.h头文件复制到项目目录下; - 将
sqlite3.lib静态库复制到项目目录下,在项目属性中配置:- 项目属性 → C/C++ → 常规 → 附加包含目录:添加
sqlite3.h所在路径; - 项目属性 → 链接器 → 常规 → 附加库目录:添加
sqlite3.lib所在路径; - 项目属性 → 链接器 → 输入 → 附加依赖项:添加
sqlite3.lib;
- 项目属性 → C/C++ → 常规 → 附加包含目录:添加
- 将
sqlite3.dll复制到项目生成的可执行文件(.exe)同级目录下(否则程序运行时会提示 "缺少 sqlite3.dll")。
- 新建 C++ 项目,将
- 编译运行:直接点击 Visual Studio 中的 "生成""运行" 按钮即可,无需额外添加链接选项。
2. 代码集成
- 将本工具类保存为
SQLiteDB.h,在业务代码中通过#include "SQLiteDB.h"引入; - 工具类无额外命名空间,直接实例化
SQLiteDB类即可使用所有接口,避免命名冲突。
三、核心功能使用步骤
1. 数据库连接管理(open/close)
- 步骤 1:创建
SQLiteDB对象,构造函数自动初始化连接句柄为安全的空状态; - 步骤 2:调用
open()传入数据库文件路径,建立连接; - 步骤 3:通过返回值判断连接是否成功,失败时调用
getErrorMsg()查看具体原因; - 步骤 4:(可选)数据库使用完成后调用
close()主动关闭连接,或依赖析构函数自动关闭(推荐)。
参数详细解析:
| 接口 | 参数名 | 详细说明 |
|---|---|---|
open() |
filename | 参数类型为 const std::string &,必填项 ,数据库文件路径: - 相对路径:"./test.db"(当前程序运行目录); - 绝对路径:"/home/user/test.db"(Linux)/ "C:\\Users\\test.db"(Windows,反斜杠需转义); - 特殊值:":memory:"(内存数据库,程序退出后数据销毁); 若文件不存在,SQLite 会自动创建空数据库;若路径无写入权限,返回连接失败错误。 |
close() |
无参数 | 无输入参数,调用后自动释放数据库连接资源,置空句柄;若句柄已为空,仅输出提示信息,无异常。 |
结果判断:
- 成功:
open()/close()返回true,open()会输出 "数据库 [路径] 连接成功"; - 失败:返回
false,控制台输出错误原因,可通过getErrorMsg()获取详细错误字符串。
2. 静态 SQL 语句执行(exec)
适用于无动态参数的 SQL 操作(如创建表、删除表、批量插入固定数据)。
- 步骤 1:确保数据库已通过
open()成功连接; - 步骤 2:准备静态 SQL 字符串(可包含多条以分号分隔的 SQL);
- 步骤 3:调用
exec()传入 SQL 字符串; - 步骤 4:通过返回值判断执行结果,失败时查看错误信息。
参数详细解析:
| 参数名 | 详细说明 |
|---|---|
| sql | 参数类型为 const std::string &,必填项 ,待执行的静态 SQL 字符串: - 示例 1(建表):"CREATE TABLE IF NOT EXISTS user (id INT PRIMARY KEY, name TEXT, age INT);"; - 示例 2(批量插入):"INSERT INTO user VALUES (1, '张三', 25); INSERT INTO user VALUES (2, '李四', 30);"; 若传入空字符串、SQL 语法错误,或数据库未连接,返回执行失败错误。 |
结果判断:
- 成功:返回
true,输出 "SQL 执行成功!SQL:[传入的 SQL]"; - 失败:返回
false,输出错误原因(如语法错误、表不存在),并释放 SQLite 内部错误信息内存。
3. 预处理 SQL 增 / 删 / 改操作(executePrepared)
适用于带动态参数的写入操作(如插入用户、更新年龄、删除指定记录),核心优势是防 SQL 注入、执行效率更高。
- 步骤 1:确保数据库已成功连接;
- 步骤 2:准备带占位符的 SQL 字符串(占位符为
?,序号从 1 开始); - 步骤 3:构造字符串 / 整数参数列表(
std::pair<占位符序号, 值>); - 步骤 4:调用
executePrepared()传入 SQL 和参数列表; - 步骤 5:通过返回值判断执行结果,失败时查看错误信息。
参数详细解析:
| 参数名 | 详细说明 |
|---|---|
| sql | 参数类型为 const std::string &,必填项 ,带占位符的 SQL 字符串: - 示例 1(插入):"INSERT INTO user (id, name, age) VALUES (?, ?, ?);"; - 示例 2(更新):"UPDATE user SET age = ? WHERE id = ?;"; 占位符序号必须与参数列表的序号一一对应,语法错误会导致编译失败。 |
| strParams | 参数类型为 const std::vector<std::pair<int, std::string>> &,可选项 ,字符串类型参数列表: - 示例:{``{2, "张三"}} 表示将第 2 个占位符绑定为字符串 "张三"; 无字符串参数时传空列表即可。 |
| intParams | 参数类型为 const std::vector<std::pair<int, int64_t>> &,可选项 ,64 位整数类型参数列表: - 示例:{``{1, 1001}, {3, 25}} 表示将第 1 个占位符绑定为 1001,第 3 个绑定为 25; 支持 int/long/long long 等整数类型(自动转换为 int64_t),无整数参数时传空列表即可。 |
结果判断:
- 成功:返回
true,输出 "预处理 SQL 执行成功!SQL:[传入的 SQL]"; - 失败:返回
false,输出错误原因(如参数序号错误、参数类型不匹配、预处理语句编译失败),并自动销毁已编译的预处理语句,避免资源泄漏。
4. 预处理 SQL 查询操作(queryPrepared)
适用于带动态参数的查询操作(如查询指定 ID 的用户、查询年龄大于 X 的用户),自动解析结果并封装为二维字符串数组。
- 步骤 1:确保数据库已成功连接;
- 步骤 2:准备带占位符的查询 SQL 字符串(无参数则占位符可省略);
- 步骤 3:构造查询参数列表(无参数则传空列表);
- 步骤 4:定义
std::vector<std::vector<std::string>>类型变量接收结果; - 步骤 5:调用
queryPrepared()传入 SQL、参数列表、结果变量; - 步骤 6:通过返回值判断查询结果,成功则遍历结果集,失败则查看错误信息。
参数详细解析:
| 参数名 | 详细说明 |
|---|---|
| sql | 参数类型为 const std::string &,必填项 ,带占位符的查询 SQL 字符串: - 示例 1(单参数):"SELECT id, name, age FROM user WHERE id = ?;"; - 示例 2(无参数):"SELECT * FROM user;"; 语法错误会导致编译失败。 |
| strParams | 参数类型为 const std::vector<std::pair<int, std::string>> &,可选项 ,查询字符串参数列表,规则同 executePrepared。 |
| intParams | 参数类型为 const std::vector<std::pair<int, int64_t>> &,可选项 ,查询整数参数列表,规则同 executePrepared。 |
| result | 参数类型为 std::vector<std::vector<std::string>> &,必填项 ,查询结果输出变量: - 外层 vector:每个元素代表一条查询记录; - 内层 vector:每个元素代表记录中的一列值; - NULL 值自动转为 "NULL" 字符串; 函数调用前会清空该变量原有数据,避免旧数据干扰。 |
结果判断:
- 成功:返回
true,输出 "查询成功!共获取到 [N] 条记录~",可遍历result获取数据; - 失败:返回
false,输出错误原因,result会被清空,禁止使用。
四、关键接口 / 成员说明
1. 公有核心接口
| 接口名 | 返回值类型 | 核心作用 | 异常 / 边界处理 |
|---|---|---|---|
SQLiteDB() |
构造函数 | 初始化数据库连接句柄为 nullptr,确保对象创建时处于安全状态 |
无,仅输出初始化提示 |
~SQLiteDB() |
析构函数 | 自动关闭已打开的数据库连接,释放资源 | 若句柄非空,调用 close();空句柄则无操作 |
open(const string&) |
bool |
建立数据库连接,自动关闭旧连接 | 路径无效 / 无权限 → 返回 false + 错误提示;连接成功后置句柄为有效状态 |
close() |
bool |
关闭数据库连接,释放句柄 | 空句柄 → 返回 true + 提示;关闭失败 → 返回 false + 错误提示;成功后置句柄为 nullptr |
getErrorMsg() |
std::string |
获取最后一次操作的错误信息 | 句柄为空 → 返回 "数据库句柄为空,无错误信息";有错误 → 返回 SQLite 原生英文错误描述 |
exec(const string&) |
bool |
执行静态 SQL,无结果返回 | 数据库未连接 / 空 SQL/SQL 语法错误 → 返回 false + 错误提示;自动释放 SQLite 错误信息内存 |
executePrepared(...) |
bool |
执行带参数的增 / 删 / 改预处理 SQL | 参数序号错误 / 类型不匹配 / SQL 编译失败 → 返回 false + 错误提示;自动销毁预处理语句 |
queryPrepared(...) |
bool |
执行带参数的查询预处理 SQL,返回结构化结果 | 查询执行失败 → 返回 false + 错误提示;自动销毁预处理语句;结果集自动处理 NULL 值 |
2. 私有成员
| 成员名 | 类型 | 访问权限 | 核心作用 | 安全控制 |
|---|---|---|---|---|
db_ |
sqlite3* |
private | 数据库连接句柄,存储 SQLite 底层连接对象 | 私有化防止外部直接修改 / 释放,仅通过类接口操作; open() 初始化,close() 销毁,析构函数兜底; 禁止空句柄操作,所有接口先校验句柄有效性 |
五、错误处理规范
所有接口均通过 bool 类型返回操作结果,并提供 getErrorMsg() 接口获取精细化错误信息,错误处理遵循以下规范:
1. 核心返回值规则
| 返回值 | 含义 | 后续操作建议 |
|---|---|---|
true |
操作成功 | 可正常使用输出参数(如 queryPrepared 的 result),执行后续业务逻辑 |
false |
操作失败 | 禁止使用输出参数;通过 getErrorMsg() 获取错误原因,针对性处理(如检查路径、SQL 语法、参数序号) |
2. 常见错误类型及原因
| 错误类型 | 典型场景 | 排查方向 |
|---|---|---|
| 连接失败 | open() 返回 false |
1. 数据库文件路径错误; 2. 程序无文件读写权限; 3. SQLite 库链接失败 |
| 无效参数 | exec()/executePrepared()/queryPrepared() 返回 false |
1. 传入空 SQL 字符串; 2. 预处理参数序号超出占位符数量; 3. 参数类型与字段类型不匹配 |
| SQL 执行失败 | exec() 返回 false |
1. SQL 语法错误(如关键字拼写错误、表 / 字段不存在); 2. 约束冲突(如主键重复) |
| 参数绑定失败 | executePrepared()/queryPrepared() 返回 false |
1. 占位符序号从 0 开始(正确应为 1); 2. 字符串参数包含非法字符(未转义); 3. 预处理语句编译失败导致无法绑定 |
| 查询失败 | queryPrepared() 返回 false |
1. 查询的表 / 字段不存在; 2. 预处理语句执行过程中异常(如数据库连接断开) |
| 资源释放失败 | close()/executePrepared() 返回 false |
1. 存在未销毁的预处理语句; 2. 数据库连接被外部非法修改 |
3. 使用规范
- 调用任何接口前,优先确保
open()已成功返回true(数据库已连接);- 调用接口后必须先判断返回值,失败场景下禁止使用输出参数(如
result);- 错误信息排查优先级:控制台输出 →
getErrorMsg()→ SQLite 官方错误码文档;- 批量操作失败时,建议单步执行定位具体错误(如先测试建表,再测试插入)。
六、补充注意事项
-
内存安全:
- 所有 SQLite 底层资源(连接句柄、预处理语句、错误信息内存)均由类自动管理,
std::unique_ptr兜底,杜绝内存泄漏; - 析构函数自动关闭连接,即使业务代码未调用
close(),也不会残留无效句柄。
- 所有 SQLite 底层资源(连接句柄、预处理语句、错误信息内存)均由类自动管理,
-
参数规范:
- 预处理语句占位符序号从 1 开始 ,查询结果列序号从 0 开始,新手需重点注意;
- 整数参数统一使用
int64_t类型,兼容 32/64 位系统,避免数值溢出; - 字符串参数默认使用
SQLITE_TRANSIENT策略(SQLite 复制字符串副本),无需担心原字符串销毁导致的野指针。
-
文件权限与路径:
- 数据库文件路径需确保程序有读写权限(Linux/Mac 可通过
chmod授权,Windows 需注意用户权限); - Windows 路径需使用双反斜杠(
\\)或正斜杠(/),避免转义错误; - 内存数据库(
:memory:)仅在程序运行期间有效,适合临时数据处理、单元测试。
- 数据库文件路径需确保程序有读写权限(Linux/Mac 可通过
-
SQL 注入防护:
- 禁止通过拼接字符串构造带参数的 SQL(如
string sql = "INSERT INTO user VALUES (" + to_string(id) + ")";); - 所有动态参数必须通过
executePrepared()/queryPrepared()绑定,从根源杜绝 SQL 注入。
- 禁止通过拼接字符串构造带参数的 SQL(如
-
性能优化:
- 批量插入 / 更新相同结构的 SQL 时,可扩展类增加预处理语句复用逻辑(当前类每次调用重新编译,适合中小规模操作);
- 查询大量数据时,建议通过
LIMIT关键字分页,避免一次性加载过多数据导致内存占用过高。
-
编码与空值处理:
- SQLite 默认使用 UTF-8 编码,需确保业务传入的字符串为 UTF-8 格式,避免中文乱码;
- 查询结果中 NULL 值自动转为 "NULL" 字符串,业务侧可通过判断该值处理空字段,无需直接操作底层 NULL 指针。
-
跨平台兼容:
- 类代码无平台相关逻辑,兼容 Linux/Mac/Windows;
- 编译时仅需调整 SQLite 库的链接方式,核心逻辑无需修改。