是否可以迭代结果集,如果满足条件,则删除当前行?
即。
之类的东西int rc;
sqlite3_stmt* statement;
sqlite3_exec(db, "BEGIN", 0, 0, 0);
sqlite3_prepare_v2(_db, "SELECT id,status,filename,del FROM mytable", -1, &statement, NULL);
rc = sqlite3_step(statement);
while (rc == SQLITE_ROW){
int id = sqlite3_column_int(statement, 1);
int status = sqlite3_column_int(statement, 2);
const unsigned char* filename = sqlite3_column_int(statement, 3);
int del = sqlite3_column_int(statement, 4);
if (status == 0 || del > 0){
int rc = unlink(filename);
if (rc == 0)
// Now delete the current row
else
// unlink failed, find out why, try again or ... ?
}
rc = sqlite3_step(statement);
}
sqlite3_finalize(statement);
sqlite3_exec(db, "COMMIT", 0, 0, 0);
我可以调用单个sql语句删除符合条件的所有行,但如果由于某种原因unlink失败,我不想这样做。
我可以调用删除当前行的操作吗?
编辑: 所以有一个名为rowid的特殊列。我只是将其添加为 先前的语句并创建另一个语句,如“从表中删除rowid =?”并传入当前的rowid?
这应该正常吗?这是最好的解决方法吗?
答案 0 :(得分:3)
就效率而言,它可能不是最有效的。如果您在数千或更多行的级别上执行此操作,则应考虑执行以下操作之一(或组合):
将您的查询更改为仅考虑del为>的行0(SELECT id,status,filename,del FROM mytable WHERE del > 0
)。您正在使用当前方法执行表扫描,您应该始终尽量避免。还要确保在del列上有索引。
构建行ID的中间数组,然后执行以下格式的查询:DELETE FROM table WHERE id IN (?)
,参数化值是您收集的行ID,它们连接成逗号分隔的字符串。根据您正在处理的行数,您可以将此删除设置为批量执行(批量大小为1000,5000等);因为它是SQLite,所以调到你正在运行的设备。
使用以下格式在连接创建时注册自定义SQLite函数:
void deleteFileFunc(sqlite3_context * context, int argc, sqlite3_value ** argv) {
assert(argc == 1);
const char * fileName = sqlite3_value_text(argv[0]);
int rc = unlink(fileName);
sqlite3_result_int(context, rc);
}
sqlite3_create_function(db, "delete_file", 1, SQLITE3_UTF8, NULL, &deleteFileFunc, NULL, NULL);
然后将数据库查询更改为DELETE FROM mytable WHERE del > 0 AND delete_file(filename) == 0
形式。只有删除成功时才会删除该行,并且您不需要迭代结果集。 SQLite 3创建功能页面:http://www.sqlite.org/c3ref/create_function.html
答案 1 :(得分:0)
直接删除行就可以了。
文档说它不会干扰正在运行的 SELECT 删除已读取的行。
但如果删除预期稍后读取的未来行,则结果未定义。