sqlite3_exec() 回调函数说明
sqlite3_exec() Callback function clarification
我无法理解 SQLite3 数据库中回调函数的使用。
我理解是用来遍历SELECT条语句多条记录的。但我不明白它是如何做到的或如何使我自己的 useful 回调。我已经通读 this tutorial 好几遍试图理解,但这对我来说并不合适。
当我使用他们的示例并在 Visual Studio 中进行调试以查看如何填充和遍历参数数组时,我迷路了。另外 VS 只显示数组中的当前槽,而不是整个数组本身。
如果您需要任何说明,请告诉我,因为我是来学习的!
我正在请求某人解释如何使用回调。也许是其他人如何使用它的一些例子。只是解释一下这个人在做什么:
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;
}
假设您有一个名为 User
的非常简单的 table,看起来像这样:
╔════╦══════════╗
║ ID ║ Name ║
╟────╫──────────╢
║ 1 ║ Slvrfn ║
║ 2 ║ Sean ║
║ 3 ║ Drew ║
║ 4 ║ mah ║
╚════╩══════════╝
然后你这样调用sqlite3_exec
(参数详细描述in the documentation):
/* Error handling omitted for brevity */
sqlite3_exec(db, "SELECT * FROM User", my_special_callback, NULL, NULL);
SQLite 将执行传递的 SQL 语句,并且对于它找到的每个结果行,它将调用 my_special_callback
。因此,对于我们的示例 User
table,my_special_callback
将被调用 4 次。所以让我们创建 my_special_callback
:
/*
* Arguments:
*
* unused - Ignored in this case, see the documentation for sqlite3_exec
* count - The number of columns in the result set
* data - The row's data
* columns - The column names
*/
static int my_special_callback(void *unused, int count, char **data, char **columns)
{
int idx;
printf("There are %d column(s)\n", count);
for (idx = 0; idx < count; idx++) {
printf("The data in column \"%s\" is: %s\n", columns[idx], data[idx]);
}
printf("\n");
return 0;
}
给定我们的示例 table 和数据,输出将如下所示:
There are 2 column(s)
The data in column "ID" is: 1
The data in column "Name" is: Slvrfn
There are 2 column(s)
The data in column "ID" is: 2
The data in column "Name" is: Sean
There are 2 column(s)
The data in column "ID" is: 3
The data in column "Name" is: Drew
There are 2 column(s)
The data in column "ID" is: 4
The data in column "Name" is: mah
现在是如何让它变得有用,这就是 sqlite3_exec
的第 4 个参数的用武之地。来自文档:
The 4th argument to sqlite3_exec() is relayed through to the 1st
argument of each callback invocation.
所以假设我们想要 运行 我们的 SQL 并构建我们所有用户姓名的链接列表。我们需要做的第一件事是改变我们调用 sqlite3_exec
:
的方式
/* Create my fictional linked list */
struct my_linked_list *head = my_linked_list_alloc();
/*
* Pass a pointer to my list as the 4th argument to sqlite3_exec. Error
* handling omitted for brevity
*/
sqlite3_exec(db, "SELECT * FROM User", my_special_callback, head, NULL);
/* My list is now built, I can do stuff with it... */
my_linked_list_traverse(head, /* ... Stuff ... */);
并修改my_special_callback
使用
/*
* Arguments:
*
* list - Pointer to a linked list of names
* count - The number of columns in the result set
* data - The row's data
* columns - The column names
*/
static int my_special_callback(void *list, int count, char **data, char **columns)
{
struct my_linked_list *head = list;
/*
* We know that the value from the Name column is in the second slot
* of the data array.
*/
my_linked_list_append(head, data[1]);
return 0;
}
现在,如果您要使用问题中包含的 callback
,您可以这样称呼它:
/*
* Pass the table name as the 4th argument to sqlite3_exec. Error
* handling omitted for brevity
*/
sqlite3_exec(db, "SELECT * FROM User", callback, "User", NULL);
输出将是:
User:
ID = 1
Name = Slvrfn
User:
ID = 2
Name = Sean
... etc ...
(除了 User:
部分将打印到 stderr 而不是 stdout)
希望这可以帮助您解决问题。如果还有不明白的地方,请告诉我。
那个教程太可怕了,因为它除了 sqlite3_exec()
.
什么都没用
在一般情况下,唯一使用sqlite3_exec()
的有用方法是将其替换为sqlite3_prepare_v2()/sqlite3_step()/sqlite3_column_*()/sqlite3_finalize()调用,以便您可以读取数据您实际需要处理的同一个地方:
sqlite3_stmt *stmt;
const char *sql = "SELECT ID, Name FROM User";
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
print("error: ", sqlite3_errmsg(db));
return;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
int id = sqlite3_column_int (stmt, 0);
const char *name = sqlite3_column_text(stmt, 1);
// ...
}
if (rc != SQLITE_DONE) {
print("error: ", sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);
我无法理解 SQLite3 数据库中回调函数的使用。
我理解是用来遍历SELECT条语句多条记录的。但我不明白它是如何做到的或如何使我自己的 useful 回调。我已经通读 this tutorial 好几遍试图理解,但这对我来说并不合适。
当我使用他们的示例并在 Visual Studio 中进行调试以查看如何填充和遍历参数数组时,我迷路了。另外 VS 只显示数组中的当前槽,而不是整个数组本身。
如果您需要任何说明,请告诉我,因为我是来学习的!
我正在请求某人解释如何使用回调。也许是其他人如何使用它的一些例子。只是解释一下这个人在做什么:
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;
}
假设您有一个名为 User
的非常简单的 table,看起来像这样:
╔════╦══════════╗ ║ ID ║ Name ║ ╟────╫──────────╢ ║ 1 ║ Slvrfn ║ ║ 2 ║ Sean ║ ║ 3 ║ Drew ║ ║ 4 ║ mah ║ ╚════╩══════════╝
然后你这样调用sqlite3_exec
(参数详细描述in the documentation):
/* Error handling omitted for brevity */
sqlite3_exec(db, "SELECT * FROM User", my_special_callback, NULL, NULL);
SQLite 将执行传递的 SQL 语句,并且对于它找到的每个结果行,它将调用 my_special_callback
。因此,对于我们的示例 User
table,my_special_callback
将被调用 4 次。所以让我们创建 my_special_callback
:
/*
* Arguments:
*
* unused - Ignored in this case, see the documentation for sqlite3_exec
* count - The number of columns in the result set
* data - The row's data
* columns - The column names
*/
static int my_special_callback(void *unused, int count, char **data, char **columns)
{
int idx;
printf("There are %d column(s)\n", count);
for (idx = 0; idx < count; idx++) {
printf("The data in column \"%s\" is: %s\n", columns[idx], data[idx]);
}
printf("\n");
return 0;
}
给定我们的示例 table 和数据,输出将如下所示:
There are 2 column(s) The data in column "ID" is: 1 The data in column "Name" is: Slvrfn There are 2 column(s) The data in column "ID" is: 2 The data in column "Name" is: Sean There are 2 column(s) The data in column "ID" is: 3 The data in column "Name" is: Drew There are 2 column(s) The data in column "ID" is: 4 The data in column "Name" is: mah
现在是如何让它变得有用,这就是 sqlite3_exec
的第 4 个参数的用武之地。来自文档:
The 4th argument to sqlite3_exec() is relayed through to the 1st argument of each callback invocation.
所以假设我们想要 运行 我们的 SQL 并构建我们所有用户姓名的链接列表。我们需要做的第一件事是改变我们调用 sqlite3_exec
:
/* Create my fictional linked list */
struct my_linked_list *head = my_linked_list_alloc();
/*
* Pass a pointer to my list as the 4th argument to sqlite3_exec. Error
* handling omitted for brevity
*/
sqlite3_exec(db, "SELECT * FROM User", my_special_callback, head, NULL);
/* My list is now built, I can do stuff with it... */
my_linked_list_traverse(head, /* ... Stuff ... */);
并修改my_special_callback
使用
/*
* Arguments:
*
* list - Pointer to a linked list of names
* count - The number of columns in the result set
* data - The row's data
* columns - The column names
*/
static int my_special_callback(void *list, int count, char **data, char **columns)
{
struct my_linked_list *head = list;
/*
* We know that the value from the Name column is in the second slot
* of the data array.
*/
my_linked_list_append(head, data[1]);
return 0;
}
现在,如果您要使用问题中包含的 callback
,您可以这样称呼它:
/*
* Pass the table name as the 4th argument to sqlite3_exec. Error
* handling omitted for brevity
*/
sqlite3_exec(db, "SELECT * FROM User", callback, "User", NULL);
输出将是:
User: ID = 1 Name = Slvrfn User: ID = 2 Name = Sean ... etc ...
(除了 User:
部分将打印到 stderr 而不是 stdout)
希望这可以帮助您解决问题。如果还有不明白的地方,请告诉我。
那个教程太可怕了,因为它除了 sqlite3_exec()
.
在一般情况下,唯一使用sqlite3_exec()
的有用方法是将其替换为sqlite3_prepare_v2()/sqlite3_step()/sqlite3_column_*()/sqlite3_finalize()调用,以便您可以读取数据您实际需要处理的同一个地方:
sqlite3_stmt *stmt;
const char *sql = "SELECT ID, Name FROM User";
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
if (rc != SQLITE_OK) {
print("error: ", sqlite3_errmsg(db));
return;
}
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
int id = sqlite3_column_int (stmt, 0);
const char *name = sqlite3_column_text(stmt, 1);
// ...
}
if (rc != SQLITE_DONE) {
print("error: ", sqlite3_errmsg(db));
}
sqlite3_finalize(stmt);