我的应用程序使用 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_reset
与 sqlite3_finalize
.
static
如果您精确地使用,此代码显然用于执行的模式(重用 sqlite3_stmt
,通过 ?
每次迭代使用新值绑定(bind) SQL 中的 sqlite3_bind_xxx
占位符,在每次后续迭代之前执行 sqlite3_reset
)是有意义的相同的 SQL 语句,但每次迭代只是绑定(bind)新值。但看起来您已经注释掉了那部分代码并删除了 ?
来自 SQL 的占位符,而是使用 stringWithFormat
构建 SQL .
最简单的解决方案就是停用 static
模式(摆脱 static
关键字,消除检查以查看它是否是 nil
,并使用 sqlite3_finalize
代替 sqlite3_reset
),你应该没问题。
其他想法:
看起来您每次更新一行时都会关闭数据库。如果您要更新大量记录,您可能需要考虑保持数据库打开。即使您决定打开和关闭数据库,在代码中的相同逻辑级别执行这些操作也可能是有意义的(要么在
updateRecord
方法内部,要么在updateRecord
方法外部)。它只是让代码更加直观。假设您决定不想重复使用先前准备的 SQL 语句来执行多个
UPDATE
语句,这将需要使用 SQLitebind
函数调用,这并不意味着您不应该考虑使用这些bind
无论如何,函数调用。虽然通过stringWithFormat
构建 SQL 看起来可能更方便,一般使用sqlite3_bind_xxx
比较好调用是因为 (a) 保护您免受注入(inject)攻击; (b) 您不必担心转义参数值,例如其中包含引号等。不要养成使用
stringWithFormat
构建 SQL 的习惯因为,作为一般规则,它很脆弱,在某些情况下,它是危险的。在 SQL 中,通常不会在数字字段值两边使用引号。
如果您决定尝试制作
static sqlite3_stmt
/sqlite3_reset
逻辑工作,两个小观察:我不会使用相同的
sqlite3_stmt
跨数据 session (即不要关闭数据库然后重新打开它)。也许它有效,但考虑到数据库是sqlite3_prepare_v2
的参数,我不会做出任何这样的假设。当您最终关闭数据库时,您确实应该调用
sqlite3_finalize
在sqlite3_stmt
上并将其设置回nil
再次。
关于ios - sqlite数据库只更新1条记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14320071/