sqlite3_exec以及回调函数的使用

sqlite3_exec 是 SQLite3 API 中用于执行 SQL 语句的函数,其函数原型为:

int sqlite3_exec(
  sqlite3* db,               /* Database handle */
  const char* sql,           /* SQL statement, UTF-8 encoded */
  sqlite3_callback callback, /* Callback function */
  void* user_data,           /* 1st argument to callback */
  char** err_msg             /* Error msg written here */
);

参数说明:

db:打开的数据库句柄,可以使用 sqlite3_open 打开。
sql:需要执行的一条或多条 SQL 语句字符串。可以包含多个 SQL 语句,以分号(;)分隔。
callback:每次执行一个 SQL 语句时,都将调用此回调函数。通常情况下使用 NULL 即可。
user_data:传递给回调函数的参数。通常情况下使用 NULL 即可。
err_msg:如果出现错误,SQLite3 会将错误信息写入此指向的缓冲区中并返回错误码。

sqlite3_exec 函数使用示例:

#include <stdio.h>
#include <sqlite3.h>

static int callback(void* data, int argc, char** argv, char** azColName) {
  int i;
  fprintf(stderr, "%s: ", (const char*) data);
 
  for(i = 0; i < argc; i++) {
    printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
  }
  printf("\n");
  return 0;
}
 
int main(int argc, char** argv) {
  sqlite3* db;
  char* zErrMsg = 0;
  int rc;
  const char* sql;
  const char* data = "Callback function called";
 
  /* Open database */
  rc = sqlite3_open("test.db", &db);
 
  if( rc ) {
    fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
    sqlite3_close(db);
    return 1;
  }
 
  /* Create SQL statement */
  sql = "SELECT * from COMPANY";
 
  /* Execute SQL statement */
  rc = sqlite3_exec(db, sql, callback, (void*) data, &zErrMsg);
 
  if( rc != SQLITE_OK ) {
    fprintf(stderr, "SQL error: %s\n", zErrMsg);
    sqlite3_free(zErrMsg);
  } else {
    fprintf(stdout, "Operation done successfully\n");
  }
  
  /* Close database */
  sqlite3_close(db);
  return 0;
}

此示例中,我们使用 sqlite3_open 打开数据库,使用 SELECT 语句查询 COMPANY 表中的所有行数据,并使用 sqlite3_exec 执行查询。在执行期间,我们使用 callback 函数处理返回的数据,最后使用 sqlite3_close 关闭数据库连接。
需要注意的是,sqlite3_exec 中包含的 SQL 语句应尽量简单,例如只包含一条查询语句,不要包含多个语句或复杂的 SQL 语句,否则容易出现内存泄漏或 SQL 注入等风险。

其中回调函数

static int callback(void* data, int argc, char** argv, char** azColName)

回调函数的参数如下:

void* data:在sqlite3_exec函数调用时,可以传递给它的第四个参数。回调函数可以使用data指针传递的数据,这个参数通常用于在回调函数中传递上下文信息。
int argc:结果集中返回的列数。
char** argv:结果集中每一行的值所组成的数组。
char** azColName:结果集中每一列的列名所组成的数组。

下面是一个使用sqlite3_exec回调函数处理多行结果集的示例代码:

typedef struct {
    int id;
    char name[20];
    int age;
} User;

static int callback(void* data, int argc, char** argv, char** azColName) {
    int i;
    User* user = (User*)data;

    for (i = 0; i < argc; i++) {
        if (strcmp(azColName[i], "id") == 0) {
            user->id = atoi(argv[i]);
        }
        if (strcmp(azColName[i], "name") == 0) {
            strcpy(user->name, argv[i]);
        }
        if (strcmp(azColName[i], "age") == 0) {
            user->age = atoi(argv[i]);
        }
    }

    return 0;
}

int main(int argc, char** argv) {
    sqlite3* db;
    char* errMsg = 0;
    int rc;
    char* sql;
    User user;

    rc = sqlite3_open("test.db", &db);

    if (rc) {
        fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
        sqlite3_close(db);
        return 1;
    }

    sql = "SELECT id, name, age FROM users";

    rc = sqlite3_exec(db, sql, callback, &user, &errMsg);

    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL error: %s\n", errMsg);
        sqlite3_free(errMsg);
    }

    sqlite3_close(db);

    return 0;
}

在上面的代码中,我们定义了一个 User 结构体,并在 callback 回调函数中将结果集中的值存储在这个结构体中。然后我们通过调用sqlite3_exec函数执行SELECT语句,并将回调函数callback作为参数传递给sqlite3_exec。在回调函数中,我们从 argv 数组中获取结果集中的每个值,并将其存储在 user 结构体的相应字段中。

需要注意的是,在回调函数中处理结果集时要根据实际情况进行错误处理,例如,需要检查传入的参数是否为空,尤其是指针类型的参数,以及在对结果集处理时是否发生了错误等情况。

同时当使用SQLite C API中的sqlite3_exec函数执行SELECT查询时,如果查询返回多行数据,SQLite将自动多次调用指定的回调函数。每次调用回调函数时,它将为查询结果集中的一行数据调用一次。回调函数将接收到查询结果中的每个列的值,并可以对它们进行处理。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_WAWA鱼_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值