ios - sqlite数据库只更新1条记录

标签 ios sqlite ios6 sql-update xcode4.5

我的应用程序使用 SQLite 数据库来存储联系人的某些数据..例如(record_ID、时间戳等)我正在尝试使用此方法使用某些值更新 SQLITE 记录。

初始化数据库后,我曾经调用这个方法。仅更新 1 条记录。即使我每次都调用这个方法来更新。

- (void) updateRecord:(int)recordID:(NSString *)sapCustId:(NSString *)sapContactId: (NSString *)timestamp {


static sqlite3_stmt *updateStmt = nil;

    if(updateStmt == nil) {
        NSString *sql = [NSString stringWithFormat:@"update contactList set sapCustId = \"%@\", sapContactId = \"%@\", timestamp = \"%@\" Where record_ID = \"%d\"", sapCustId, sapContactId, timestamp, recordID];

        const char *sql_stmt = [sql UTF8String];

        if(sqlite3_prepare_v2(databaseHandle, sql_stmt, -1, &updateStmt, NULL) != SQLITE_OK)
            NSAssert1(0, @"Error while creating update statement. '%s'", sqlite3_errmsg(databaseHandle));
    }

//        sqlite3_bind_text(updateStmt, 0, [sapCustId UTF8String], -1, SQLITE_TRANSIENT);
//        sqlite3_bind_text(updateStmt, 1, [sapContactId UTF8String], -1, SQLITE_TRANSIENT);
//        sqlite3_bind_int(updateStmt, 2, recordID);
//        sqlite3_bind_text(updateStmt, 3, [timestamp UTF8String], -1, SQLITE_TRANSIENT);

    if(SQLITE_DONE != sqlite3_step(updateStmt))
        NSAssert1(0, @"Error while updating. '%s'", sqlite3_errmsg(databaseHandle));

sqlite3_reset(updateStmt);
sqlite3_close(databaseHandle);

//Reclaim all memory here.
[sapContactId release];
[sapCustId release];

}

请告诉我,如何解决?

最佳答案

关键问题是您的代码正在构建 updateStmt仅一次,因为那是 static你正在检查它是否不是 nil 。因此,第一个 SQL 语句正在构建,但其余的都没有构建。最简单的修复方法就是删除 static限定符以及 if(updateStmt == nil) ...逻辑,你应该去参加比赛。另外,请确保替换 sqlite3_resetsqlite3_finalize .

static如果您精确地使用,此代码显然用于执行的模式(重用 sqlite3_stmt ,通过 ? 每次迭代使用新值绑定(bind) SQL 中的 sqlite3_bind_xxx 占位符,在每次后续迭代之前执行 sqlite3_reset )是有意义的相同的 SQL 语句,但每次迭代只是绑定(bind)新值。但看起来您已经注释掉了那部分代码并删除了 ?来自 SQL 的占位符,而是使用 stringWithFormat 构建 SQL .

最简单的解决方案就是停用 static模式(摆脱 static 关键字,消除检查以查看它是否是 nil ,并使用 sqlite3_finalize 代替 sqlite3_reset ),你应该没问题。


其他想法:

  1. 看起来您每次更新一行时都会关闭数据库。如果您要更新大量记录,您可能需要考虑保持数据库打开。即使您决定打开和关闭数据库,在代码中的相同逻辑级别执行这些操作也可能是有意义的(要么在 updateRecord 方法内部,要么在 updateRecord 方法外部)。它只是让代码更加直观。

  2. 假设您决定不想重复使用先前准备的 SQL 语句来执行多个 UPDATE语句,这将需要使用 SQLite bind函数调用,这并不意味着您不应该考虑使用这些 bind无论如何,函数调用。虽然通过 stringWithFormat 构建 SQL 看起来可能更方便,一般使用 sqlite3_bind_xxx 比较好调用是因为 (a) 保护您免受注入(inject)攻击; (b) 您不必担心转义参数值,例如其中包含引号等。

    不要养成使用 stringWithFormat 构建 SQL 的习惯因为,作为一般规则,它很脆弱,在某些情况下,它是危险的。

  3. 在 SQL 中,通常不会在数字字段值两边使用引号。

  4. 如果您决定尝试制作 static sqlite3_stmt/sqlite3_reset逻辑工作,两个小观察:

    • 我不会使用相同的sqlite3_stmt跨数据 session (即不要关闭数据库然后重新打开它)。也许它有效,但考虑到数据库是 sqlite3_prepare_v2 的参数,我不会做出任何这样的假设。

    • 当您最终关闭数据库时,您确实应该调用 sqlite3_finalizesqlite3_stmt 上并将其设置回nil再次。

关于ios - sqlite数据库只更新1条记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14320071/

相关文章:

ios - Github API 回调地址

ios - 当文本字段位于 ScrollView 内时,如何使键盘具有像默认应用程序中一样的行为?

ios - Swift - 按钮中的属性字符串

iphone - 具有不同页面宽度的 UIScrollview

sql - 查询以检查是否有任何以输入字符串开头的行

python - 查询在 SQL Server 中工作但在 sqlite 中不起作用

linux - 备用 SQlite 备份解决方案

objective-c - IOS 6 奇怪的调整大小

ios - 使用 iOS Facebook SDK 发布到 friend 墙

ios - 如何在 CollectionView 中添加页脚/页眉