sqlite数据库只更新1条记录

时间:2013-01-14 14:12:05

标签: ios sqlite ios6 sql-update xcode4.5

我的应用程序使用SQLite数据库来存储联系人的某些数据..比如(record_ID,timestamp等)我试图使用这种方法用某些值更新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];

}

让我知道。,如何解决?

2 个答案:

答案 0 :(得分:1)

关键问题是,您的代码只构建updateStmt一次,因为它是static并且您正在检查它是否不是{{1} }}。因此,第一个SQL语句正在构建,但其余的都没有。最简单的解决方法是摆脱nil限定符以及static逻辑,你应该参加比赛。另外,请务必将if(updateStmt == nil) ...替换为sqlite3_reset

此代码明确用于执行的sqlite3_finalize模式(在SQL中重用static,绑定sqlite3_stmt占位符,每次迭代通过?执行新值,执行{ {1}}在每次后续迭代之前)如果你正在使用完全相同的SQL语句但只是在每次迭代时绑定新值,那么这是有意义的。但看起来您已经注释掉了部分代码并从SQL中删除了sqlite3_bind_xxx占位符,而是使用sqlite3_reset构建SQL。

最简单的解决方案是退出?模式(删除stringWithFormat关键字,取消检查以查看它是否为static,然后使用{{ 1}}代替static),你应该没事。


其他想法:

  1. 每次更新单行时,您似乎都在关闭数据库。如果您要更新一堆记录,您可能需要考虑保持数据库处于打开状态。即使您决定打开和关闭数据库,在代码中处于相同逻辑级别(在nil方法内部或在sqlite3_finalize方法之外)都可能有意义。 。它只是为了提供更直观的代码。

  2. 假设您决定不想重复使用以前准备好的SQL语句来执行多个sqlite3_reset语句,这些语句将要求使用SQLite updateRecord函数调用,这并不意味着你不应该考虑使用那些updateRecord函数调用。虽然通过UPDATE构建SQL可能看起来更方便,但通常最好使用bind调用,因为(a)可以保护您免受注入攻击; (b)您不必担心转义参数值,例如,在其中加上引号等等。

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

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

  4. 如果您决定尝试stringWithFormat / sqlite3_bind_xxx逻辑工作,那么会有两个小的意见:

    • 我不会在数据会话中使用相同的stringWithFormat(即不要关闭数据库然后重新打开它)。也许它有效,但鉴于数据库是static sqlite3_stmt的参数,我不会做出任何这样的假设。

    • 当你最后关闭数据库时,你真的应该在sqlite3_reset上拨打sqlite3_stmt并再次将其设置回sqlite3_prepare_v2

答案 1 :(得分:0)

您没有打开数据库: -

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

//OPEN DATABASE HERE
[gss initDatabase]; 
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_finalize(updateStmt);
sqlite3_close(databaseHandle);

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

}

添加我在评论中写过的开放数据库的代码。

希望它可以帮助你..