【问题标题】:SQLite Transaction Syntax for iOSiOS 的 SQLite 事务语法
【发布时间】:2012-08-26 19:49:46
【问题描述】:

我想遍历一个对象数组并根据 ID 更新 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 语句如何,每次更新都会访问数据库。我很确定这是因为 step 语句,但如果我删除它,更新就不会发生。我希望一次编写所有更新。是否可以使用 sqlite3_exec 并且仍然为数组中的每个对象绑定变量?还是我应该以不同的方式准备声明?任何关于交易内部应该是什么样子的例子都会对我有很大的帮助!

【问题讨论】:

    标签: ios sqlite syntax transactions sql-update


    【解决方案1】:

    你的方法会如你所愿;即使 sqlite 正在访问磁盘,在您提交之前,其他事务也看不到更新。因此,从这个意义上说,它们是“一次全部编写的”。

    如果将 prepare 移到循环之外,您的代码可能会更有效率。如果这样做,请在循环内使用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);
    

    【讨论】:

    • 是否需要调用sqlite3_close(db);交易后???在我的情况下,我在整个应用程序的工作过程中只打开一次 db。
    • @Swati:不需要关闭数据库;这来自问题中的代码。无限期地打开数据库是完全可以的,而且很常见。
    猜你喜欢
    • 2011-09-28
    • 1970-01-01
    • 2012-06-24
    • 2017-01-17
    • 2014-11-21
    • 1970-01-01
    • 2012-07-04
    • 1970-01-01
    • 2012-02-08
    相关资源
    最近更新 更多