【问题标题】:FMDB Update query not workingFMDB 更新查询不起作用
【发布时间】:2014-08-27 21:53:06
【问题描述】:

我有一个不工作的 FMDB 更新查询。这是我的代码:

FMDatabase *db = [self openDatabase];

if (![db open]) {
    return;
}

NSString *updateMeeting = [NSString stringWithFormat:@"UPDATE meetings SET MEETING_DESCRIPTION=\"%@\" WHERE MEETING_ID=\"%@\"",meeting.meetingDescription, meeting.meetingId];

[db beginTransaction];
[db executeQuery:updateMeeting];
[db commit];
[db close];

这些是我检查过的:

  1. 我传递的属性是对象而不是 nil。
  2. 网上有的地方用\"%@\",有的用'%@',有的用%@,有的用?。这些都不适合我。
  3. 我 NSLoged 我的字符串,它看起来像这样:

    UPDATE meetings SET MEETING_DESCRIPTION="AAA12" WHERE MEETING_ID="791D8251-2FC4-498B-85B3-C1002C04E329:F1C40061-1308-4179-B72E-7E3EEDB85E1A"
    
  4. 我想我的数据库可能找不到这个 meetingID,所以我运行了一个 SELECT 查询这个 messageID 并找到了它。

我几乎绝望了。谁能想到我没试过的东西?

谢谢

【问题讨论】:

  • 很高兴您发现了 executeUpdateexecuteQuery 的问题。一些不相​​关的观察: 1. 绝对使用? 占位符(不带引号)并将meetingDescriptionmeetingId 作为参数传递给executeUpdate 方法。这在执行插入任何用户输入的 SQL 时至关重要(因为 stringWithFormat 不会正确转义用户输入中的引号,而 ? 占位符方法完全绕过了这个问题)。
  • 2.在执行单个 UPDATE 语句时,beginTransactioncommit 是不必要的(SQLite 在您执行它们时自动提交每个更新语句)。如果在单个事务中执行许多更新 SQL 语句,那么 beginTransactioncommit 非常有用,但是在执行单个 UPDATE 语句时,它是不必要的(虽然没有坏处)。 3. 我建议你总是检查这些 FMDB 方法的返回值,否则你就瞎了。对于UPDATE 语句,您可能还需要调用[db changes] 来确认更新了多少行。

标签: objective-c fmdb


【解决方案1】:

好吧,伙计们,

感谢我的同事,我找到了答案。

方法 [db executeQuery:updateMeeting] 错误,应该改用 [db executeUpdate:updateMeeting];

这很烦人,因为我认为 Update 也是一个查询,但是 hack 是什么......它现在可以工作了 :)

【讨论】:

  • 正确。 executeUpdate 不仅准备 SQL 语句,还调用 sqlite3_step 来实际执行 SQL。另一方面,executeQuery 方法仅准备 SQL(并绑定您传递给它的任何值),依赖于 FMResultSet 方法 next 在您遍历结果集时实际调用 sqlite3_step
【解决方案2】:

你应该使用这个

[db executeUpdate:@"INSERT INTO myTable VALUES (?)", yourVar];

而不是

stringWithFormat

另外,我用它来交易

FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:YOUR_PATH];

[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
    [db executeUpdate:@"UPDATE meetings SET MEETING_DESCRIPTION=? WHERE MEETING_ID=?",meeting.meetingDescription, meeting.meetingId"];

    if (!db) {
        NSLog(@"Some problems... again...")
        *rollback = YES;
        return;
    } }];

如果你需要全局队列,你有解决方案FMDatabaseQueue Error: database is locked

【讨论】:

  • 好建议。使用? 占位符而不是stringWithFormat 是非常好的做法。这显然不是bug的来源,但是如果他恰好有引号,OP的代码就会失败!
【解决方案3】:

试试这个可能会解决你的问题。编码愉快!!!!

FMDatabase *db = [self openDatabase];

    if (![db open]) {
        return;
    }

    NSString *updateMeeting = [NSString stringWithFormat:@"UPDATE meetings SET MEETING_DESCRIPTION = ? WHERE MEETING_ID = ?"];

    NSArray *paramList = @[meeting.meetingDescription, meeting.meetingId];
    [db beginTransaction];
    [db executeQuery:updateMeeting withArgumentsInArray:paramList];
    [db commit];
    [db close];

【讨论】:

  • 是的,这应该使用executeUpdate 才能工作。但是在 SQL 中使用? 占位符的想法是一个很好的建议。如果不想创建paramList,也可以使用executeUpdate的可变参数,即[db executeUpdate:updateMeeting, meeting.meetingDescription, meeting.meetingId]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多