| 本篇讲解了如何在Visual studio开发的C++桌面应用程序内使用Sqlite数据库,Sqlite的语法和Mysql是一样的,所以本篇文章不对数据库语法做过多介绍,介绍一些常用Sqlite的API | 
|   ★提高阅读体验★ 👉 ♠一级标题 👈👉 ♥二级标题 👈👉 ♥ 三级标题 👈👉 ♥ 四级标题 👈 | 
目录
- ♠ 引入sqlite
- ♥ 下载源代码
- ♥ 复制源码
- ♥ 打开项目解决方案
- ♥ 查看所有文件
- ♥ 包括进项目
- ♥ 查看新增文件
- ♥ 不使用预制头
- ♥ 引用
 
- ♠ 查看sqlite文件
- ♠ 操作数据库
- ♥ 打开数据库
- ♥ Sql文本转换
- ♥ 绑定参数
- ♥ 执行语句
- ♥ 重置语句
- ♥ 获取结果集
- ♥ 销毁准备语句
- ♥ 封装执行语句
- ♥ 关闭数据库连接
 
- ♠ 增删改查
- ♥ 增
- ♥ 删
- ♥ 改
- ♥ 查
 
- ♠ 推送
- ♠ 结语
♠ 引入sqlite
♥ 下载源代码

传送门:官方下载地址
♥ 复制源码

将源码复制到我们的工程目录下
♥ 打开项目解决方案

 
默认打开工程就应该有的,右侧没显示去视图内找一下
♥ 查看所有文件

 
选择资源管理器下的展示所有文件,目录会展示我们路径下的所有文件
♥ 包括进项目

找到我们复制的项目,右键选择包括到项目中即可
♥ 查看新增文件

再次点击展示所有文件返回之前目录,我们已经可以看到新增的文件了
♥ 不使用预制头

选择两个c文件,右键选择C/C++ ——> 预编译头,选择不使用预编译头
♥ 引用

在文件内可以引用我们新增的文件了,目录就是跟目下的路径,没有报错就是引用成功了
♠ 查看sqlite文件
推荐使用工具SQLite Expert Professional功能很强大,不仅能够查看Sqlite数据库文件,还能做增删改查等操作

传送门:下载地址
♠ 操作数据库
♥ 打开数据库
sqlite3_open接口根据路径名去打开一个sqlite文件,如果不存在则在路径下创建一个,返回的是一个数据库连接对象
- zFilename : 路径名
- ppDb:数据库连接对象

sqlite3_open返回一个int值,SQLITE_OK常量是sqlite3.h里默认声明,返回值等于它即打开成功
- 演示用例
sqlite3 *db = NULL;
if (sqlite3_open("test.db", &db) == SQLITE_OK) {
    //todo
}
♥ Sql文本转换
sqlite3_prepare接口是解析和编译字符Sql语句,返回值用来判断执行状态和sqlite3_open相同,官方推荐使用sqlite3_prepare_v2新接口
- db:数据库连接对象
- zSql:使用UTF-8编码的Sql语句
- nBytes:表示Sql语句的长度,如果为-1则全部读取zSql
- ppStmt:指向编译后的数据结构
- pzTail:如果zSql没有读取完,剩下的会被指向pzTail,pzTail一般是Null

sqlite3_stmt数据结构就是sqlite3_prepare执行后编译好的Sql语句存储对象

- 演示用例
if (sqlite3_prepare_v2(db, sql_createtable, -1, &stmt, NULL) == SQLITE_OK) {
    //todo
}
上述代码通过sqlite3_prepare_v2接口编译了一条Sql语句sql_createtable,编译结果指向了stmt
♥ 绑定参数
sqlite3_bind_XXX接口用用来绑定参数,Sql语句在书写的时候如果需要参数,不会直接书写,而是以?代替,sqlite3_bind_XXX接口的作用就是将参数绑定到一个个问号的位置,类似于格式化字符串
- 参数1:sqlite3_stmtSql语句编译后的数据结构
- 参数2:int需要代替的问号位置
- 参数3:代替问号的值
- 参数4:有些接口没有,有的有,这里指绑定字节的长度,填-1就是全部读取
- 参数5:两个选项SQLITE_STATIC指SQLite假定该信息位于静态非托管空间中,不需要释放,SQLITE_TRANSIENT则SQLite会在绑定后返回之前自己创建内存托管,一般使用这个


- 演示用例
sqlite3_bind_text(stmt, 1, key, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, value, -1, SQLITE_TRANSIENT);
上述代码希望通过sql_select声明的Sql 语句向kv表插入数据,插入的key和value用(?,?)代替,通过sqlite3_bind_text函数将希望存储的key和value绑定到了Sql语句的问号处
♥ 执行语句
sqlite3_step接口用来执行编译好的Sql语句,新版本其返回值是SQLITE_ROW和SQLITE_DONE两个常量,SQLITE_ROW指当前还有数据没有读取完毕,SQLITE_DONE指Sql语句已经执行完成
- pStmt:唯一参数指编译后的Sql语句数据结构

- 演示用例
if (sqlite3_step(stmt) == SQLITE_DONE) {
    //todo
}
上述代码sqlite3_step执行了存储编译后Sql语句的数据结构stmt
♥ 重置语句
sqlite3_reset语句会把sqlite3_stmt 结构重置到sqlite3_prepare_v2执行后sqlite3_step执行前的状态
- pStmt:唯一参数就是一个需要被重置的sqlite3_stmt实例

♥ 获取结果集
sqlite3_column_XXX接口通过在sqlite3_step执行过后,从sqlite3_stmt的实例中获取查询到的结果,多用于查询
- 参数1:sqlite3_stmt的实例,结果集存储在内
- 参数2:iCol,查询结果的索引值

对于不同类型存在不同的结果筛选语句
♥ 销毁准备语句
sqlite3_finalize方法会销回sqlite3_prepare_XX方法创建的sqlite3_stmt实例
- 参数1:唯一参数为sqlite3_stmt实例

♥ 封装执行语句
sqlite3_exec语句相当于sqlite3_prepare_v2,sqlite3_step和sqlite3_finalize的封装,简便的同时对应着其效率会更低
- 参数1:打开的数据库sqlite3实例
- 参数2:sql的执行局与
- 参数3:sql执行完的回调函数
- 参数4:传递给回调函数的指针参数
- 参数5:错误信息

♥ 关闭数据库连接
sqlite3_close接口的调用将关闭之前使用sqlite3_open打开的数据库连接,任何与这个连接相关的准备语句必须在调用这个关闭函数之前被释放
- 参数1:唯一参数为sqlite3数据库连接对象实例

♠ 增删改查
上述的部分我们已经基本介绍了和操作数据库相关的所有步骤,接下来我们看一下增删改查的演示代码
♥ 增
我们创建一个名为test.db的数据库,并增加名为test_tbl的表
- 创建数据库文件和表
sqlite3 *db = NULL;
if (sqlite3_open("test.db", &db) == SQLITE_OK) {
   const char *sql_createtable = "CREATE TABLE test_tbl(key TEXT,value TEXT)";
   sqlite3_stmt *stmt = NULL;
   if (sqlite3_prepare_v2(db, sql_createtable, -1, &stmt, NULL) == SQLITE_OK) {
	   if (sqlite3_step(stmt) == SQLITE_DONE) {
		   OutputDebugString(L"create table done");
	   }
	   sqlite3_reset(stmt);
   }
   sqlite3_finalize(stmt);
}
sqlite3_close(db);

 
上述代码我们创建了一个test.db的数据库文件,并创建了一个包含key和value的名为test_tbl的表,从工具内可以看到,目前没有数据
- 插入数据
sqlite3 *db = NULL;
if (sqlite3_open("test.db", &db) == SQLITE_OK) {
   const char *sql_select = "INSERT INTO test_tbl(key,value) VALUES(?,?)";
   sqlite3_stmt *stmt = NULL;
   if (sqlite3_prepare_v2(db, sql_select, -1, &stmt, NULL) == SQLITE_OK) {
	   sqlite3_bind_text(stmt, 1, "test_key", -1, SQLITE_TRANSIENT);
	   sqlite3_bind_text(stmt, 2, "test_value", -1, SQLITE_TRANSIENT);
	   if (sqlite3_step(stmt) == SQLITE_DONE) {
		   OutputDebugString(L"insert success");
	   }
	   sqlite3_reset(stmt);
   }
   sqlite3_finalize(stmt);
}
sqlite3_close(db);

上述代码我们插入了一条数据进入到表test_tbl内
♥ 删
sqlite3 *db = NULL;
if (sqlite3_open("test.db", &db) == SQLITE_OK) {
   const char *sql_select = "DELETE FROM test_tbl WHERE key LIKE ?";
   //DELETE FROM test_tbl WHERE key LIKE 'test_key'
   
   sqlite3_stmt *stmt = NULL;
   if (sqlite3_prepare_v2(db, sql_select, -1, &stmt, NULL) == SQLITE_OK) {
	   sqlite3_bind_text(stmt, 1, "test_key", -1, SQLITE_TRANSIENT);
	   if (sqlite3_step(stmt) == SQLITE_DONE) {
		   OutputDebugString(L"delete success");
	   }
	   sqlite3_reset(stmt);
   }
   sqlite3_finalize(stmt);
}
sqlite3_close(db);

上述代码我们从表test_tbl内删除了key="test_key"的值
♥ 改
sqlite3 *db = NULL;
if (sqlite3_open("test.db", &db) == SQLITE_OK) {
   const char *sql_select = "UPDATE test_tbl SET value =? WHERE key =? ";
   sqlite3_stmt *stmt = NULL;
   if (sqlite3_prepare_v2(db, sql_select, -1, &stmt, NULL) == SQLITE_OK) {
	   sqlite3_bind_text(stmt, 1, "hahahahahahahahahahah", -1, SQLITE_TRANSIENT);
	   sqlite3_bind_text(stmt, 2, "test_key", -1, SQLITE_TRANSIENT);
	   if (sqlite3_step(stmt) == SQLITE_DONE) {
		   OutputDebugString(L"insert success");
	   }
	   sqlite3_reset(stmt);
   }
   sqlite3_finalize(stmt);
}
sqlite3_close(db);

上述代码我们从表test_tbl内将key=“test_key"的值修改成"hahahahahahahahahahah”
♥ 查
sqlite3 *db = NULL;
if (sqlite3_open("test.db", &db) == SQLITE_OK) {
   const char *sql_select = "SELECT value FROM test_tbl WHERE key=?";
   sqlite3_stmt *stmt = NULL;
   if (sqlite3_prepare_v2(db, sql_select, -1, &stmt, NULL) == SQLITE_OK) {
	   sqlite3_bind_text(stmt, 1, "test_key", -1, SQLITE_TRANSIENT);
	   int ret = sqlite3_step(stmt);
	   if (ret == SQLITE_DONE || ret == SQLITE_ROW) {
		   const char *val = (const char*)sqlite3_column_text(stmt, 0);
	   }
	   sqlite3_reset(stmt);
   }
   sqlite3_finalize(stmt);
}
sqlite3_close(db);

上述代码我们从表test_tbl内获取了key=“test_key"对应的值”
♠ 推送
- Github
https://github.com/KingSun5
♠ 结语
若是觉得博主的文章写的不错,不妨关注一下博主,点赞一下博文,另博主能力有限,若文中有出现什么错误的地方,欢迎各位评论指摘。
 本文属于原创文章,转载请著名作者出处并置顶!!



















