如何通过C/C++ sqlite3接口遍历查询返回行的各字段值
问题根源
你遇到的现象由两个问题共同导致:
- 数组下标越界:回调函数的
argv参数是从0开始索引的,你写的cout << argv[1];属于越界访问。当前你程序读到的VERTEX表查询结果只有1列,有效下标只有0,越界读刚好拿到了相邻内存里存储的相同字符串"ale",所以才会重复输出两次"ale"。 - 数据库连接错误:你代码里用相对路径打开
test.db,程序实际连接的是运行时工作目录下的数据库文件,和你预期存了多列数据的数据库不是同一个文件,所以读到的表只有1列1行数据,自然没法拆分多列值。
sqlite3_exec回调参数说明
要正确取单行内的每个字段值,先明确回调四个入参的含义:
argc:当前结果行的列总数azColName:字符串数组,长度与argc一致,按顺序存储每一列的列名argv:字符串数组,长度与argc一致,按顺序存储当前行每一列的字段值,注意argv数组下标从0开始;如果字段值为NULL,对应位置的指针为空- 第一个
void*类型参数:是你调用sqlite3_exec时传入的第4个参数,用于透传自定义数据,传0时无实际作用 - 回调返回0时会继续处理下一行结果,返回非0值会直接中断查询
修正代码
修正后的回调函数
补全空值判断,去掉越界访问的代码:
static int callback(void *NotUsed, int argc, char **argv, char **azColName) { cout << "===== 单行数据分割线 =====" << endl; for (int i = 0; i < argc; i++) { const char* val = argv[i] ? argv[i] : "NULL"; cout << azColName[i] << " = " << val << endl; } return 0; }
修正后的查询函数
补全数据库连接校验、关闭逻辑,建议用绝对路径指定数据库文件避免连错:
void retrieve_vertex_from_db() { sqlite3 *db; // 替换为你的数据库文件实际绝对路径 int ret = sqlite3_open("/your/actual/path/test.db", &db); if (ret != SQLITE_OK) { cerr << "数据库打开失败: " << sqlite3_errmsg(db) << endl; sqlite3_close(db); return; } string sql = "SELECT * FROM VERTEX;"; char *errMsg = nullptr; ret = sqlite3_exec(db, sql.c_str(), callback, nullptr, &errMsg); if (ret != SQLITE_OK) { cerr << "查询执行失败: " << errMsg << endl; sqlite3_free(errMsg); } else { cout << "查询执行成功" << endl; } sqlite3_close(db); }
排查指引
如果修正后仍读不到多列数据,按以下步骤排查:
- 打开程序实际连接的数据库文件,执行
.schema VERTEX确认表结构,执行SELECT * FROM VERTEX;确认表内实际存储的数据,和你预期的多列数据是否一致 - 检查之前插入数据的逻辑,确认是否给所有列都插入了有效值
- 运行程序前确认当前工作目录,避免读到其他路径下的旧版本test.db文件
内容的提问来源于stack exchange,提问作者Alejandro
相关产品推荐
相关产品推荐

