sqlite api

SQLiteDB 工具类使用说明


一、工具概述

本工具基于 SQLite3 C API 封装,支持 C++11+ 标准,提供轻量级、高易用性的 SQLite 数据库操作能力:

  1. 连接管理:数据库连接的创建 / 关闭全生命周期自动化,自动处理旧连接、空句柄等边界场景;
  2. SQL 执行
    • 静态 SQL:支持无参数的建表、删表、批量插入等操作(封装 sqlite3_exec);
    • 预处理 SQL:支持带参数的增 / 删 / 改 / 查操作(封装 sqlite3_prepare_v2/sqlite3_bind_*/sqlite3_step),从根源避免 SQL 注入;
  3. 结果处理:查询结果自动封装为二维字符串数组,NULL 值统一转换为 "NULL" 字符串,无需手动解析底层数据结构;
  4. 健壮性:完善的参数校验、错误信息反馈、资源自动释放机制,避免内存泄漏、野指针、文件句柄泄漏等问题,降低程序崩溃风险。

二、前置准备步骤

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 为例)
  1. 安装 SQLite3 开发库(包含头文件和静态 / 动态库):

    复制代码
    sudo apt update
    sudo apt install libsqlite3-dev
  2. 验证安装是否成功:

    复制代码
    sqlite3 --version  # 查看 SQLite3 版本
    ls /usr/include/sqlite3.h  # 查看头文件是否存在
    ls /usr/lib/x86_64-linux-gnu/libsqlite3.so  # 查看动态库是否存在
  3. 编译时,需在编译命令中添加 -lsqlite3 选项,链接 SQLite3 动态库,示例编译命令:

    复制代码
    g++ -std=c++11 -o test_sqlite test_sqlite.cpp SQLiteDB.cpp -lsqlite3
(2)Mac 系统
  1. 方式一:通过 Homebrew 安装(推荐):

    复制代码
    brew install sqlite3
  2. 方式二:手动下载源码编译安装(适合需要指定版本的场景):

    • 从 SQLite 官方网站(https://www.sqlite.org/download.html)下载源码包(如 sqlite-autoconf-3440000.tar.gz);

    • 解压源码包,进入解压目录,执行以下命令编译安装:

      复制代码
      ./configure
      make
      sudo make install
  3. 编译时,同样需添加 -lsqlite3 选项链接库文件,示例编译命令:

    复制代码
    g++ -std=c++11 -o test_sqlite test_sqlite.cpp SQLiteDB.cpp -lsqlite3
(3)Windows 系统
  1. 下载 SQLite3 库文件:
    • 从 SQLite 官方网站下载适用于 Windows 的预编译库(包含头文件 sqlite3.h、静态库 sqlite3.lib、动态库 sqlite3.dll);
    • 推荐下载 "Precompiled Binaries for Windows" 中的 "sqlite-amalgamation-XXXXXXX.zip"(包含头文件和源码)和 "sqlite-dll-win64-x64-XXXXXXX.zip"(包含动态库)。
  2. 项目配置(以 Visual Studio 2022 为例):
    • 新建 C++ 项目,将 sqlite3.h 头文件复制到项目目录下;
    • sqlite3.lib 静态库复制到项目目录下,在项目属性中配置:
      1. 项目属性 → C/C++ → 常规 → 附加包含目录:添加 sqlite3.h 所在路径;
      2. 项目属性 → 链接器 → 常规 → 附加库目录:添加 sqlite3.lib 所在路径;
      3. 项目属性 → 链接器 → 输入 → 附加依赖项:添加 sqlite3.lib
    • sqlite3.dll 复制到项目生成的可执行文件(.exe)同级目录下(否则程序运行时会提示 "缺少 sqlite3.dll")。
  3. 编译运行:直接点击 Visual Studio 中的 "生成""运行" 按钮即可,无需额外添加链接选项。
2. 代码集成
  • 将本工具类保存为 SQLiteDB.h,在业务代码中通过 #include "SQLiteDB.h" 引入;
  • 工具类无额外命名空间,直接实例化 SQLiteDB 类即可使用所有接口,避免命名冲突。

三、核心功能使用步骤

1. 数据库连接管理(open/close)
  1. 步骤 1:创建 SQLiteDB 对象,构造函数自动初始化连接句柄为安全的空状态;
  2. 步骤 2:调用 open() 传入数据库文件路径,建立连接;
  3. 步骤 3:通过返回值判断连接是否成功,失败时调用 getErrorMsg() 查看具体原因;
  4. 步骤 4:(可选)数据库使用完成后调用 close() 主动关闭连接,或依赖析构函数自动关闭(推荐)。

参数详细解析

接口 参数名 详细说明
open() filename 参数类型为 const std::string &必填项 ,数据库文件路径: - 相对路径:"./test.db"(当前程序运行目录); - 绝对路径:"/home/user/test.db"(Linux)/ "C:\\Users\\test.db"(Windows,反斜杠需转义); - 特殊值:":memory:"(内存数据库,程序退出后数据销毁); 若文件不存在,SQLite 会自动创建空数据库;若路径无写入权限,返回连接失败错误。
close() 无参数 无输入参数,调用后自动释放数据库连接资源,置空句柄;若句柄已为空,仅输出提示信息,无异常。

结果判断

  • 成功:open()/close() 返回 trueopen() 会输出 "数据库 [路径] 连接成功";
  • 失败:返回 false,控制台输出错误原因,可通过 getErrorMsg() 获取详细错误字符串。
2. 静态 SQL 语句执行(exec)

适用于无动态参数的 SQL 操作(如创建表、删除表、批量插入固定数据)。

  1. 步骤 1:确保数据库已通过 open() 成功连接;
  2. 步骤 2:准备静态 SQL 字符串(可包含多条以分号分隔的 SQL);
  3. 步骤 3:调用 exec() 传入 SQL 字符串;
  4. 步骤 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. 步骤 1:确保数据库已成功连接;
  2. 步骤 2:准备带占位符的 SQL 字符串(占位符为 ?,序号从 1 开始);
  3. 步骤 3:构造字符串 / 整数参数列表(std::pair<占位符序号, 值>);
  4. 步骤 4:调用 executePrepared() 传入 SQL 和参数列表;
  5. 步骤 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. 步骤 1:确保数据库已成功连接;
  2. 步骤 2:准备带占位符的查询 SQL 字符串(无参数则占位符可省略);
  3. 步骤 3:构造查询参数列表(无参数则传空列表);
  4. 步骤 4:定义 std::vector<std::vector<std::string>> 类型变量接收结果;
  5. 步骤 5:调用 queryPrepared() 传入 SQL、参数列表、结果变量;
  6. 步骤 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 操作成功 可正常使用输出参数(如 queryPreparedresult),执行后续业务逻辑
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. 使用规范
  1. 调用任何接口前,优先确保 open() 已成功返回 true(数据库已连接);
  2. 调用接口后必须先判断返回值,失败场景下禁止使用输出参数(如 result);
  3. 错误信息排查优先级:控制台输出 → getErrorMsg() → SQLite 官方错误码文档;
  4. 批量操作失败时,建议单步执行定位具体错误(如先测试建表,再测试插入)。

六、补充注意事项

  1. 内存安全

    • 所有 SQLite 底层资源(连接句柄、预处理语句、错误信息内存)均由类自动管理,std::unique_ptr 兜底,杜绝内存泄漏;
    • 析构函数自动关闭连接,即使业务代码未调用 close(),也不会残留无效句柄。
  2. 参数规范

    • 预处理语句占位符序号从 1 开始 ,查询结果列序号从 0 开始,新手需重点注意;
    • 整数参数统一使用 int64_t 类型,兼容 32/64 位系统,避免数值溢出;
    • 字符串参数默认使用 SQLITE_TRANSIENT 策略(SQLite 复制字符串副本),无需担心原字符串销毁导致的野指针。
  3. 文件权限与路径

    • 数据库文件路径需确保程序有读写权限(Linux/Mac 可通过 chmod 授权,Windows 需注意用户权限);
    • Windows 路径需使用双反斜杠(\\)或正斜杠(/),避免转义错误;
    • 内存数据库(:memory:)仅在程序运行期间有效,适合临时数据处理、单元测试。
  4. SQL 注入防护

    • 禁止通过拼接字符串构造带参数的 SQL(如 string sql = "INSERT INTO user VALUES (" + to_string(id) + ")";);
    • 所有动态参数必须通过 executePrepared()/queryPrepared() 绑定,从根源杜绝 SQL 注入。
  5. 性能优化

    • 批量插入 / 更新相同结构的 SQL 时,可扩展类增加预处理语句复用逻辑(当前类每次调用重新编译,适合中小规模操作);
    • 查询大量数据时,建议通过 LIMIT 关键字分页,避免一次性加载过多数据导致内存占用过高。
  6. 编码与空值处理

    • SQLite 默认使用 UTF-8 编码,需确保业务传入的字符串为 UTF-8 格式,避免中文乱码;
    • 查询结果中 NULL 值自动转为 "NULL" 字符串,业务侧可通过判断该值处理空字段,无需直接操作底层 NULL 指针。
  7. 跨平台兼容

    • 类代码无平台相关逻辑,兼容 Linux/Mac/Windows;
    • 编译时仅需调整 SQLite 库的链接方式,核心逻辑无需修改。
相关推荐
j_xxx404_2 小时前
力扣--分治(快速排序)算法题II:数组中的第K个最大元素(Top K问题),LCR159.库存管理III
数据结构·c++·算法·leetcode
ysa0510302 小时前
运用map优化多次查询【Kadomatsu 子序列】
数据结构·c++·笔记·算法
24白菜头2 小时前
第十五届蓝桥杯C&C++大学B组
数据结构·c++·笔记·学习·算法·leetcode·蓝桥杯
代码探秘者3 小时前
【算法篇】1.双指针
java·数据结构·人工智能·后端·python·算法
wengqidaifeng3 小时前
备战蓝桥杯----C/C++组 (一)数据结构与STL讲解(上):顺序表、链表、栈与队列——从手写到调用,一文搞懂四种线性结构
c语言·数据结构·蓝桥杯
01二进制代码漫游日记3 小时前
动态顺序表的实现(修改)
数据结构·算法
计算机安禾3 小时前
【C语言程序设计】第38篇:链表数据结构(二):链表的插入与删除操作
c语言·开发语言·数据结构·c++·算法·链表
jing-ya3 小时前
day 57 图论part9
java·开发语言·数据结构·算法·图论
cjforever143 小时前
数据结构整理-二叉树
数据结构