sqlite 编程指南

sqlite 编程指南 SQLite 是轻量级、无服务器、零配置的嵌入式数据库无需单独安装服务直接以文件形式存储非常适合桌面应用、移动端、小型后端项目。基于官方sqlite3C API轻量嵌入式数据库开发核心接口、CRUD、事务、回调查询全覆盖。环境准备安装库# Ubuntu/Debian sudo apt install libsqlite3-dev # 编译链接参数 gcc demo.c -o demo -lsqlite3头文件引入#include sqlite3.h #include stdio.h #include stdlib.h核心数据结构与返回码sqlite3*数据库句柄sqlite3_stmt*预编译 SQL 语句句柄常用返回值SQLITE_OK0成功SQLITE_ERROR1通用错误基础流程打开数据库sqlite3_open预处理 SQLsqlite3_prepare_v2绑定参数sqlite3_bind_xxx执行语句sqlite3_step读取结果sqlite3_column_xxx查询用重置语句sqlite3_reset复用语句销毁语句sqlite3_finalize关闭数据库sqlite3_close数据库连接 API1. 打开 / 创建数据库int sqlite3_open( const char *filename, // 数据库文件名 sqlite3 **ppDb // 输出数据库句柄 );返回SQLITE_OK表示成功生成sqlite3*句柄后续所有操作都靠它2. 关闭数据库int sqlite3_close(sqlite3 *db);必须在所有语句finalize之后调用程序退出前必须关闭防止锁文件执行 SQL API两种方式方式 1简单执行 SQLsqlite3_exec适合建表、增删改、无返回值 / 简单查询int sqlite3_exec( sqlite3 *db, // 句柄 const char *sql, // SQL 语句 int (*callback)(void*,int,char**,char**), // 回调查询 void *arg, // 传给回调的参数 char **errmsg // 错误信息 );回调函数格式固定写法int callback(void *data, int argc, char **argv, char **azColName) { // argc列数 // argv值数组 // azColName列名数组 return 0; }方式 2预编译 API推荐防注入、高效最常用、最安全、企业开发必用1. 预编译 SQLint sqlite3_prepare_v2( sqlite3 *db, const char *sql, int nByte, // -1 表示自动计算长度 sqlite3_stmt **ppStmt, // 输出语句句柄 const char **pzTail );2. 绑定参数? 占位符下标从1 开始sqlite3_bind_int(stmt, 1, 20); // 整数 sqlite3_bind_text(stmt, 2, 张三, -1, SQLITE_STATIC); // 字符串 sqlite3_bind_double(stmt, 3, 95.5); // 浮点数 sqlite3_bind_null(stmt, 4); // NULL3. 执行一步int sqlite3_step(sqlite3_stmt *stmt);返回SQLITE_ROW还有下一行数据返回SQLITE_DONE执行完成4. 读取一行中的列值int sqlite3_column_int(stmt, 0); // 第0列 int const unsigned char* sqlite3_column_text(stmt, 1); // 第1列 string double sqlite3_column_double(stmt, 2); // 第2列 浮点数5. 释放预编译语句int sqlite3_finalize(sqlite3_stmt *stmt);事务 APIsqlite3_exec(db, BEGIN;, NULL, 0, err); // 开始事务 sqlite3_exec(db, COMMIT;, NULL, 0, err); // 提交 sqlite3_exec(db, ROLLBACK;, NULL, 0, err); // 回滚错误处理 APIconst char *sqlite3_errmsg(sqlite3 *db); // 获取错误信息 int sqlite3_errcode(sqlite3 *db); // 获取错误码 void sqlite3_free(void *p); // 释放错误信息常用返回值SQLITE_OK 0 成功 SQLITE_ROW 100 还有一行数据 SQLITE_DONE 101 执行完成 SQLITE_ERROR 1 错误 SQLITE_BUSY 5 数据库被占用分类精简流程1. 无结果操作增 / 删 / 改打开 → 预编译 → 绑参 → 执行 → 重置 (批量) → 销毁 → 关闭2. 查询操作打开 → 预编译 → 绑参 → 循环 step 取行 → 读取字段 → 销毁 → 关闭3. 批量操作打开 → 开启事务 → 单次预编译 → 循环绑参 执行 重置 → 提交事务 → 销毁 → 关闭标准调用顺序1. 打开数据库sqlite3_open ↓ 2. 开启事务BEGIN【批量操作必须】 ↓ 3. 预编译 SQLsqlite3_prepare_v2【只执行 1 次】 ↓ 循环执行 N 次 ↓ 绑定参数sqlite3_bind_xxx ↓ 执行一步sqlite3_step ↓ 重置语句sqlite3_reset ↓ 4. 提交事务COMMIT ↓ 5. 释放预编译语句sqlite3_finalize ↓ 6. 关闭数据库sqlite3_close严格顺序图解sqlite3_open ↓ sqlite3_prepare_v2 -- 只做一次 ↓ 循环开始 ↓ sqlite3_bind_xxx -- 每次都绑 ↓ sqlite3_step -- 每次都执行 ↓ sqlite3_reset -- 每次都重置 循环结束 ↓ sqlite3_finalize -- 最后释放 ↓ sqlite3_close完整示例代码建表、增删改查基础#include sqlite3.h #include stdio.h static int callback(void *data, int argc, char **argv, char **azColName) { for(int i 0; i argc; i) { printf(%s %s\n, azColName[i], argv[i] ? argv[i] : NULL); } printf(----------------\n); return 0; } int main() { sqlite3 *db; char *errMsg; int ret; const char *sql; // 1. 打开数据库不存在自动创建 ret sqlite3_open(test.db, db); if(ret ! SQLITE_OK) { fprintf(stderr, 打开失败: %s\n, sqlite3_errmsg(db)); sqlite3_close(db); return 1; } // 2. 创建表 sql CREATE TABLE IF NOT EXISTS user( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER);; ret sqlite3_exec(db, sql, NULL, 0, errMsg); if(ret ! SQLITE_OK) { fprintf(stderr, 建表错误: %s\n, errMsg); sqlite3_free(errMsg); } // 3. 插入数据 sql INSERT INTO user(name, age) VALUES(张三,20); INSERT INTO user(name, age) VALUES(李四,22);; ret sqlite3_exec(db, sql, NULL, 0, errMsg); if(ret ! SQLITE_OK) { fprintf(stderr, 插入错误: %s\n, errMsg); sqlite3_free(errMsg); } // 4. 查询数据回调函数遍历结果 sql SELECT * FROM user;; ret sqlite3_exec(db, sql, callback, 0, errMsg); if(ret ! SQLITE_OK) { fprintf(stderr, 查询错误: %s\n, errMsg); sqlite3_free(errMsg); } // 5. 更新数据 sql UPDATE user SET age21 WHERE name张三;; sqlite3_exec(db, sql, NULL, 0, errMsg); // 6. 删除数据 sql DELETE FROM user WHERE name李四;; sqlite3_exec(db, sql, NULL, 0, errMsg); // 关闭数据库 sqlite3_close(db); return 0; }预编译语句防注入、高效参数绑定推荐业务使用避免字符串拼接 SQLvoid bindInsert(sqlite3 *db) { sqlite3_stmt *stmt; const char *sql INSERT INTO user(name, age) VALUES(?, ?);; // 预编译SQL sqlite3_prepare_v2(db, sql, -1, stmt, NULL); // 绑定参数 下标从1开始 sqlite3_bind_text(stmt, 1, 王五, -1, SQLITE_STATIC); sqlite3_bind_int(stmt, 2, 25); // 执行语句 sqlite3_step(stmt); // 重置语句可重复复用 sqlite3_reset(stmt); // 销毁语句句柄 sqlite3_finalize(stmt); }遍历查询结果逐行读取void selectRow(sqlite3 *db) { sqlite3_stmt *stmt; const char *sql SELECT id,name,age FROM user;; sqlite3_prepare_v2(db, sql, -1, stmt, NULL); // 循环读取每一行 while(sqlite3_step(stmt) SQLITE_ROW) { int id sqlite3_column_int(stmt, 0); const unsigned char *name sqlite3_column_text(stmt, 1); int age sqlite3_column_int(stmt, 2); printf(id:%d name:%s age:%d\n, id, name, age); } sqlite3_finalize(stmt); }事务操作批量操作加事务保证原子性void transaction(sqlite3 *db) { sqlite3_exec(db, BEGIN TRANSACTION;, NULL, 0, NULL); // 多条数据库操作 sqlite3_exec(db, INSERT INTO user(name,age) VALUES(小明,18);,NULL,0,NULL); sqlite3_exec(db, INSERT INTO user(name,age) VALUES(小红,19);,NULL,0,NULL); // 提交 sqlite3_exec(db, COMMIT;, NULL, 0, NULL); // 出错回滚sqlite3_exec(db, ROLLBACK;, NULL, 0, NULL); }