深⼊理解SQLite3之sqlite3_exec及回调函数
sqlite3的C/C++接⼝API主要有3个重要函数,分别为
11、sqlite3_open(const char* filename, sqlite3 **ppDb);
22、int sqlite3_exec(
3      sqlite3*,                                  /* An open database */
4      const char *sql,                          /* SQL to be evaluated */
5      int (*callback)(void*,int,char**,char**),  /* Callback function */
6      void *,                                    /* 1st argument to callback */
7      char **errmsg                              /* Error msg written here */
8    );
9
103、sqlite3_close(sqlite3*)
sqlite3_open和sqlite3_close是很好理解的,分别是打开和关闭对应的数据库。⽽sqlite3_exec函数是sqlite3的API函数,可以实现各种功能,所以理解sqlite3_exec对于实际的 编程⼗分有必要,我们来详细分析sqlite3_exec函数,
1、sqlite3_exec函数 形参
1sqlite3*            : open 打开的数据库
2const char* sql,    : 执⾏的sql功能语句
3*callback,          : sql语句对应的回调函数
4void* data,        : 传递给回调函数的指针参数
5char **errmsq      : 错误信息
其中 const char* sql表⽰ 相应的 sql语句,如果我们直接在linux下,使⽤shell是可以实现所有的sqlite功能的,但是如果进⾏C或C++开发程序时,很明显是没有shell可⽤的,所以这个 *sql就是对应sqlite
功能命令的 “字符串”,后⾯我们举例来分析。回调函数指针callback则是 *sql功能命令对应的 回调函数,所谓 回调函数的意思是,会先执⾏*sql对应的功能命令,然后将结果传递给回调函数,回调函数根据结果再进⼀步执⾏。这代表着,这个 “回调函数”才是最有意义的,我们要讲我们需要的功能,通过回调函数来实现,不管是获取数据库表中有效信息,还是其他动作。
2、sqlite3_exec的回调函数 callback
我们还是来先看下回调函数的参数:
1typedef int(*sqlite_callback)(void* para, int columenCount, char** columnValue, char** columnName);
2
3参数:
4para : 由sqlite3_exec传⼊的参数指针,或者说是指针参数
columnCount: 查询到的这⼀条记录由多少个字段(多少列)
1columnValue : 该参数是双指针,查询出来的数据都保存在这⾥,它是⼀个1维数组,每⼀个元素都是⼀
2个char*,是⼀个字段内容,所以这个参数就可以不是单字节,⽽是可以为字符串等不定
3长度的数值,⽤字符串表⽰,以'\0'结尾。
4
1columnName : 该参数是双指针,语columnValue是对应的,表⽰这个字段的字段名称,
2
3返回    : 执⾏成果则返回SQLITE_OK,否则返回其他值
这⾥⾯有⼏个地⽅容易理解错,回调函数的参数⼀定是 sql功能命令执⾏结果的进⼀步处理,其中para好理解,就是sqlite3_exec传递的参数,
columnCount:表⽰sql功能结果的“字段”,也就是“列”的个数,没错,就是“列”的个数。
另外需要特别注意的是:回调函数多数时候不是执⾏1次,⽽是会循环执⾏n次,当我们使⽤select进
⾏sql功能时,往往输出的结果会是多⾏,那么 有n⾏,就会执⾏n次的 回调函数。举例如下:
1#include <stdio.h>
2#include <stdlib.h>
3#include <sqlite3.h>
4
5static int callback(void *data, int argc, char **argv, char **azColName){
6  int i;
7  fprintf(stderr, "%s: ", (const char*)data);
8  for(i=0; i<argc; i++){
9      printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
10  }
11  printf("\n");
12  return 0;
13}
14
15int main(int argc, char* argv[])
16{
17  sqlite3 *db;
18  char *zErrMsg = 0;
19  int rc;
20  char *sql;
21  const char* data = "Callback function called";
22
23  /* Open database */
24  rc = sqlite3_open("test.db", &db);
25  if( rc ){
26      fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
27      exit(0);
28  }else{
29      fprintf(stderr, "Opened database successfully\n");
30  }
31
32  /* Create SQL statement */
33  sql = "SELECT * from COMPANY";
34
35  /* Execute SQL statement */
36  rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
37  if( rc != SQLITE_OK ){
38      fprintf(stderr, "SQL error: %s\n", zErrMsg);
39      sqlite3_free(zErrMsg);
40  }else{
41      fprintf(stdout, "Operation done successfully\n");
42  }
43  sqlite3_close(db);
44  return 0;
45}
1"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) "  \
2        "VALUES (1, 'Paul', 32, 'California', 20000.00 ); " \
3        "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) "  \
4        "VALUES (2, 'Allen', 25, 'Texas', 15000.00 ); "    \
5        "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" \
6        "VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );" \
7        "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" \
8        "VALUES (4, 'Mark', 25, 'Rich-Mond ', 65000.00 );";
所以执⾏的结果:
1Opened database successfully
2Callback function called: ID = 1
3NAME = Paul
4AGE = 32
5ADDRESS = California
6SALARY = 20000.0
7
8Callback function called: ID = 2
9NAME = Allen
10AGE = 25
11ADDRESS = Texas
12SALARY = 15000.0
13
14Callback function called: ID = 3
15NAME = Teddy
16AGE = 23
17ADDRESS = Norway
18SALARY = 20000.0
19
20Callback function called: ID = 4
21NAME = Mark
fprintf作用22AGE = 25
23ADDRESS = Rich-Mond
24SALARY = 65000.0
25
26Operation done successfully
可以看出来,由于sql命令⾏为 select* from COMPANY,该命令会将表中所有信息都输出,总共5个字段(列),包含4条信息(⾏),所以这个回调函数会被执⾏4次,理解这个逻辑,⾮常重要。
⽽且回调函数的后两个参数是 双指针 ,也就是 指针的指针,包含了2层的指向,⾥层的 指向是 对应具体的数据指针,外层的指向则是 数据指针序号,也可以理解成 “列”索引。我们通过这两个指针能够进⼀步 编写 ⾃定义功能代码。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。