2012-08-26 37 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:没有必要关闭数据库;来自问题中的代码。无限期地开放分贝是完全可以的,而且很常见。 –