2011-02-08 77 views
3

是否可以遍历一个结果集,如果条件满足,删除当前行?删除sqlite3的当前行,而遍历一个结果集

即像

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语句删除符合条件的所有行,但我不想这样做,如果出于某种原因取消链接失败。

我可以调用一个操作来删除当前行?

编辑: 因此,有一个叫ROWID专栏。我只是补充说,作为 先前的语句中的一列,并创建另一个语句,如“从表中删除rowid =?”并传入当前的rowid?

这应该是正确的?这是最好的方法吗?

+0

好的,以及我得到它使用rowid工作。但仍然想知道这是否是最有效的方法。 – Matt 2011-02-08 03:10:10

回答

3

就效率而言,这可能不是最有效的。如果你这样做的东西上十万行的更大数量级别,您应该考虑做以下的一个(或组合):

  • 查询更改为只考虑其行是德尔> 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

+0

谢谢,这是非常有用的信息。我没有意识到sqlite支持类似存储过程的东西。 – Matt 2011-02-08 14:01:42