彻底搞懂SQLite回调函数查询

一、理解回调函数

1.回调函数流程

  1. 主函数需要调用回调函数
  2. 中间函数登记回调函数
  3. 触发回调函数事件
  4. 调用回调函数
  5. 响应回调事件

2.回调函数实例

比如你在美团上点了个外卖,并填写了电话号码,外卖员把快递送到楼下,打电话给你,然后你来取外卖。
在这个例子里,你的电话号码就叫回调函数,填电话号码叫登记回调函数,外卖送到指点地点叫做回调事件,外卖员给你打电话叫做 调用回调函数,你到楼下去买卖叫做 响应回调事件。

3.回调函数方式

  • 同步回调是阻塞的,单个的线程需要等待结果的返回才能继续执行。就像你点了外卖,点完外卖之后要一直等,知道等到电话通知才去取外卖。
  • 异步回调是,在同时指定一个函数,在异步任务完成时会自动的调用这个函数。就像你你点了外卖后可以先做自己的事情,看会动漫电影,然后外卖员打电话叫你再去取外卖。

二、sqlite3_exec的回调函数 callback

1.先看sqlite3_exec()

int sqlite3_exec(sqlite3*, const char *sql, sqlite3_callback, void *, char **errmsg );
  • 第1个参数是打开数据库时得到的指针。

  • 第2个参数const char *sql 是一条 sql 语句,以/0结尾。

  • 第3个参数sqlite3_callback 是回调,当这条语句执行之后,sqlite3会去调用你提供的这个函数。

  • 第4个参数void * 是你所提供的指针,你可以传递任何一个指针参数到这里,这个参数最终会传到回调函数里面,如果不需要传递指针给回调函数,可以填NULL。等下我们再看回调函数的写法,以及这个参数的使用。

  • 第5个参数char ** errmsg 是错误信息。注意是指针的指针。sqlite3里面有很多固定的错误信息。执行 sqlite3_exec 之后,执行失败时可以查阅这个指针(直接printf(“%s/n”,errmsg))得到一串字符串信息,这串信息告诉你错在什么地方。sqlite3_exec函数通过修改你传入的指针的指针,把你提供的指针指向错误提示信息,这样sqlite3_exec函数外面就可以通过这个char*得到具体错误提示。

说明

通常,sqlite3_callback 和它后面的 void * 这两个位置都可以填 NULL。填NULL表示你不需要回调。比如你做insert 操作,做 delete 操作,就没有必要使用回调。而当你做 select 时,就要使用回调,因为 sqlite3 把数据查出来,得通过回调告诉你查出了什么数据。

2.在看回调callback()

typedef int (*sqlite3_callback)(void*,int,char**, char**);
  • para:是你在 sqlite3_exec 里传入的 void * 参数,通过para参数,你可以传入一些特殊的指针(比如类指针、结构指针),然后在这里面强制转换成对应的类型(这里面是void*类型,必须强制转换成你的类型才可用),然后操作这些数据。
  • n_column:是这一条记录有多少个字段 (即这条记录有多少列) 。
  • char ** column_value:是个关键值,查出来的数据都保存在这里,它实际上是个1维数组(不要以为是2维数组),每一个元素都是一个 char * 值是一个字段内容(用字符串来表示,以/0结尾,需要根据需要强制转换成对应的类型)。
  • char ** column_name: 跟column_value是对应的,表示这个字段的字段名称。

你的回调函数必须定义成上面这个函数的类型。下面给个简单的例子:

//sqlite3的回调函数
//sqlite 每查到一条记录,就调用一次这个回调
static int callback(void *NotUsed, int argc, char **argv, char **azColName)

看一下回调函数callback。必须是static的, 可以是类的成员函数。

其中的形参argc, argv, azColName是sqlite_exec帮我们填写的。 argc是查询语句返回的字段数目。

  • argv:是查询到的一条记录的各个字段 。
  • zaColName:是每一列的域名 。

比如这样一张表 MYTABLE

 ID    NAME     ADDRESS    AGE
 1   trulyliu   ShangHai   25 
 2    sunfyer   ShangHai   25

执行 select * from MYTABLE

当查询到第一条纪录,回调被运行时 argc = 4 总共4个字段

argv[0]  argv[1]  argv[2]  argv[3] 的值分别是
 1     trulyliu   ShangHai  25  
zaColName[0]  zaColName[1]  zaColName[2]  zaColName[3] 的值
  ID             NAME         ADDRESS        AGE  

第二条记录被查询到时 argc = 4 总共4个字段

argv[0]  argv[1]  argv[2]  argv[3] 的值分别是
 1     trulyliu  ShangHai   25  
zaColName[0]  zaColName[1]  zaColName[2]  zaColName[3] 的值 
 ID         NAME          ADDRESS            AGE   

注意,查询到的这些值都是char*类型,可能需要做类型转换,以满足我们的要求。

3.再看sqlite3_exec()

加入我有一张表USER

						NAME    PASSWD
						zcl      123
						lyf      456
						hfh      789

现在执行下面的语句。

char sql[100] = "select * from USER where NAME = 'ym' and PASSWD = 000";
ret = sqlite3_exec(db,sql,callback,(void*)para,&errmsg);
if(res != SQLITE_OK)        
{
	printf("查询失败\n");
}
else
{
	printf("查询成功\n");
}

猜一下执行结果会是什么。
你可能会想,USER表中不存在name=‘ym’,passwd='000’的数据,所以结果会打印“查询失败”,一开始我也是这么想的,但是事与愿违,无论我查询的数据是什么,结果都打印“查询成功”,这是怎么回事呢?我试着把res的值输出来,结果总是0,先来看看sqlite3.h的中的宏定义。

#define SQLITE_OK         0 /*成功结果*/
#define SQLITE_ERROR      1 /*SQL错误或缺少数据库*/
#define SQLITE_INTERNAL   2 /*SQLite中的内部逻辑错误*/
#define SQLITE_PERM       3 /*访问权限被拒绝*/
#define SQLITE_ABORT      4 /*回调例程请求中止*/
#define SQLITE_BUSY       5 /*数据库文件已锁定*/
#define SQLITE_LOCKED     6 /*数据库中的一个表被锁定*/
#define SQLITE_NOMEM      7 /*一个malloc()失败*/
#define SQLITE_READONLY   8 /*尝试写入只读数据库*/
#define SQLITE_INTERRUPT  9 /*由sqlite3_interrupt()终止的操作*/
#define SQLITE_IOERR      10 /*发生某种磁盘I/O错误*/
#define SQLITE_CORRUPT    11 /*数据库磁盘映像格式不正确*/
#define SQLITE_NOTFOUND   12 /*未知操作码sqlite3_interrupt()*/
#define SQLITE_FULL       13 /*插入失败,因为数据库已满*/
#define SQLITE_CANTOPEN   14 /*无法打开数据库文件*/
#define SQLITE_PROTOCOL   15 /*数据库锁协议错误*/
#define SQLITE_EMPTY      16 /*数据库为空*/
#define SQLITE_SCHEMA     17 /*数据库架构已更改*/
#define SQLITE_TOOBIG     18 /*字符串或BLOB超出大小限制*/
#define SQLITE_CONSTRAINT 19 /*由于约束冲突而中止*/
#define SQLITE_MISMATCH   20 /*数据类型不匹配*/
#define SQLITE_usage      21 /*库使用错误*/
#define SQLITE_NOLFS      22 /*使用主机不支持的操作系统功能*/
#define SQLITE_AUTH       23 /*授权被拒绝*/
#define SQLITE_FORMAT     24 /*辅助数据库格式错误*/
#define SQLITE_RANGE      25 /*第二个参数定义为sqlite3_bind超出范围*/
#define SQLITE_NOTADB     26 /*打开的不是数据库文件的文件*/
#define SQLITE_NOTICE     27 /*来自sqlite3_log()的通知*/
#define SQLITE_WARNING    28 /*来自sqlite3_log()的警告*/
#define SQLITE_ROW        100 /*sqlite3_step()已准备好另一行*/
#define SQLITE_DONE       101 /*sqlite3_step()已完成执行*/

#define SQLITE_OK 0 /*成功结果*/
意味着sqlite3_exec(db,sql,NULL,NULL,&errmsg)这条语句已经执行成功,虽然没有查询到数据,但是成功执行就意味SQLITE_OK,所以SQLITE_OK就是0,这里要注意查询不到数据不意味查询失败,这是一个很重要的认识。

三、参考

Sqlite回调函数的使用技巧
关于回调函数和Sqlite3 回调函数的理解
sqlite3.h的常用宏定义,错误代码

  • 12
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈喽朝龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值