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将自动多次调用指定的回调函数。每次调用回调函数时,它将为查询结果集中的一行数据调用一次。回调函数将接收到查询结果中的每个列的值,并可以对它们进行处理。