2012-08-26 38 views
2

我想遍歷一個對象數組,並根據ID在SQLite數據庫中更新相應的行。我想在一次交易中做到這一點。我知道我可以使用:iOS的SQLite事務語法

sqlite3_exec(db, "BEGIN", 0, 0, 0); 
sqlite3_exec(db, "COMMIT", 0, 0, 0); 

但是,我不確定如何編寫事務內的更新語句。我需要將不同的變量綁定到該語句。現在代碼如下所示:

-(void)someUpdateMethod 
{ 
    sqlite3 *db; 

    //Establish connection to db 
    if (sqlite3_open([[self dbFilePath] UTF8String], &db) == SQLITE_OK) 
    { 
     const char *query = "UPDATE Table SET Value1 = ?, Value2 = ?"; 

     sqlite3_stmt *compiledStatement = nil; 

     sqlite3_exec(db, "BEGIN EXCLUSIVE TRANSACTION", 0, 0, 0); 
     for (someObject *obj in uArray) 
     { 
      // Repeated statement - This is what I'm not sure of... 
      if(sqlite3_prepare(db, query, -1, &compiledStatement, NULL) == SQLITE_OK) 
      { 
       sqlite3_bind_int(compiledStatement, 1, [obj value1]); 
       sqlite3_bind_int(compiledStatement, 2, [obj value2]); 
      } 
      if (sqlite3_step(compiledStatement) != SQLITE_DONE) NSLog(@"DB not updated. Error: %s",sqlite3_errmsg(db)); 
      if (sqlite3_finalize(compiledStatement) != SQLITE_OK) NSLog(@"SQL Error: %s",sqlite3_errmsg(db)); 
     } 
     if (sqlite3_exec(db, "COMMIT TRANSACTION", 0, 0, 0) != SQLITE_OK) NSLog(@"SQL Error: %s",sqlite3_errmsg(db)); 
     sqlite3_close(db); 
    } 
    else 
    NSLog(@"sql-error: %s", sqlite3_errmsg(db)); 
} 

不管Begin和Commit語句如何,數據庫都在每個Update上訪問。我很確定這是因爲步驟聲明,但如果我刪除它,更新不會發生。我希望一次寫入所有更新。是否有可能使用sqlite3_exec並仍爲數組中的每個對象綁定變量?或者,我應該準備這份聲明有不同的方式嗎?任何交易內部應該看起來像什麼的例子都會對我有很大的幫助!

回答

10

你的方法可以按你的意願工作;即使sqlite正在訪問磁盤,在您提交之前更新對其他事務不可見。所以,從這個意義上說,他們是「一次寫完」。

如果您在循環之外移動準備工作,您的代碼效率會更高。如果你這樣做,在循環內使用sqlite3_reset,循環後使用sqlite3_finalize

sqlite3_exec(db, "BEGIN EXCLUSIVE TRANSACTION", 0, 0, 0); 
    if(sqlite3_prepare(db, query, -1, &compiledStatement, NULL) == SQLITE_OK) 
    { 
    for (someObject *obj in uArray) 
    { 
     sqlite3_bind_int(compiledStatement, 1, [obj value1]); 
     sqlite3_bind_int(compiledStatement, 2, [obj value2]); 
     if (sqlite3_step(compiledStatement) != SQLITE_DONE) NSLog(@"DB not updated. Error: %s",sqlite3_errmsg(db)); 
     if (sqlite3_reset(compiledStatement) != SQLITE_OK) NSLog(@"SQL Error: %s",sqlite3_errmsg(db)); 
    } 
    } 
    if (sqlite3_finalize(compiledStatement) != SQLITE_OK) NSLog(@"SQL Error: %s",sqlite3_errmsg(db)); 
    if (sqlite3_exec(db, "COMMIT TRANSACTION", 0, 0, 0) != SQLITE_OK) NSLog(@"SQL Error: %s",sqlite3_errmsg(db)); 
    sqlite3_close(db); 
+0

是否需要調用sqlite3_close(db);交易完成後在我的情況下,我只在應用程序的整個工作過程中打開db一次。 – Swati

+1

@Swati:沒有必要關閉數據庫;來自問題中的代碼。無限期地開放分貝是完全可以的,而且很常見。 –