2011-02-08 79 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