【问题标题】:Foreign keys in FMDatabaseQueueFMDatabaseQueue 中的外键
【发布时间】:2023-03-11 23:43:01
【问题描述】:

所以我正在使用 FMDB 库,我想启用通过

完成的外键
[db executeQuery:@"PRAGMA foreign_keys=ON"];

但我使用的是 FMDatabaseQueue,像这样初始化

-(FMDatabaseQueue*)queue
{

    if (_queue == nil)
    {
        FMDatabaseQueue* queue = [FMDatabaseQueue databaseQueueWithPath:self.dbPath];
        _queue = queue;
    }
    return _queue;
} 

然后我就这样使用它

-(NSNumber*)phoneDBID:(NSString*)phoneNumber
{
    __block NSNumber* phoneDBID = nil;
    [self.queue inDatabase:^(FMDatabase *db) {
        FMResultSet* result = [db executeQuery:@"SELECT * from Contact_numbers where number= ?;", phoneNumber];
        if ([result next])
        {
            phoneDBID = [NSNumber numberWithInt:[result intForColumn:@"contact_id"]];
        }
        [result close];
    }];
    return phoneDBID;
}

我认为队列中没有启用外键,有没有办法为队列启用它们,或者我必须在每个查询中都这样做?

【问题讨论】:

    标签: objective-c sqlite fmdb


    【解决方案1】:

    两个观察结果:

    1. 关于FMDatabaseQueue 的外键约束的唯一警告是,我建议不要在FMDatabaseQueue 事务中(即在inTransaction 块中)使用PRAGMA foreign_keysThe documentation for PRAGMA foreign_keys 说:

      此编译指示是事务中的空操作;只有在没有待处理的BEGINSAVEPOINT 时,才能启用或禁用外键约束强制。

      不过,如果您在 inDatabase 块内执行此编译指示,您会没事的。

    2. 您的示例并未说明foreign_keys 的实际应用。外键约束仅在修改数据库中的数据时适用。但是你只是在做SELECT,所以PRAGMA foreign_keys的设置无关紧要。

      为了说明这个 pragma 的用法,请考虑以下示例。我创建了bookauthor 表,其中前者具有后者的外键:

      [queue inDatabase:^(FMDatabase *db) {
          success = [db executeUpdate:@"create table author (author_id integer primary key, name text)"];
          if (!success) NSLog(@"Create author table failed: %@", [db lastErrorMessage]);
      
          success = [db executeUpdate:@"create table book (book_id integer primary key, author_id integer, title text, FOREIGN KEY(author_id) REFERENCES author(author_id))"];
          if (!success) NSLog(@"Create book table failed: %@", [db lastErrorMessage]);
      }];
      

      如果没有 foreign_keys 编译指示,这可行:

      [queue inDatabase:^(FMDatabase *db) {
      
          // without foreign key constraints enforced, this will succeed, even though the author_id has not yet been added to author table
      
          success = [db executeUpdate:@"insert into book (book_id, author_id, title) values (?, ?, ?)", @(1), @(101), @"Romeo and Juliet"];
          if (!success) NSLog(@"Insert 'Romeo and Juliet' failed: %@", [db lastErrorMessage]);
      
          // obviously, this will, too
      
          success = [db executeUpdate:@"insert into author (author_id, name) values (?, ?)", @(101), @"William Shakespeare"];
          if (!success) NSLog(@"Insert 'William Shakespeare' failed: %@", [db lastErrorMessage]);
      }];
      

      但是如果我打开外键:

      [queue inDatabase:^(FMDatabase *db) {
      
          // turn on foreign keys
      
          success = [db executeUpdate:@"PRAGMA foreign_keys = YES"];
          if (!success) NSLog(@"Foreign keys pragma failed: %@", [db lastErrorMessage]);
      }];
      

      如果再试一次,book 的第一次插入没有相应的author 条目会失败。在插入 author 条目之前,我无法插入 book 条目:

      [queue inDatabase:^(FMDatabase *db) {
      
          // with foreign key this should (and does) fail
      
          success = [db executeUpdate:@"insert into book (book_id, author_id, title) values (?, ?, ?)", @(2), @(201), @"One Hundred Years of Solitude"];
          if (!success) NSLog(@"First insert of 'Hundred Years of Solitude' failed: %@", [db lastErrorMessage]);
      
          // but if we insert author ...
      
          success = [db executeUpdate:@"insert into author (author_id, name) values (?, ?)", @(201), @"Gabriel García Márquez"];
          if (!success) NSLog(@"Insert 'Gabriel García Márquez' failed: %@", [db lastErrorMessage]);
      
          // ... now this will succeed.
      
          success = [db executeUpdate:@"insert into book (book_id, author_id, title) values (?, ?, ?)", @(2), @(201), @"One Hundred Years of Solitude"];
          if (!success) NSLog(@"Second insert 'Hundred Years of Solitude' failed: %@", [db lastErrorMessage]);
      }];
      

    因此,总而言之,外键与FMDatabaseQueue 配合使用都很好,但我只建议不要在inTransaction 调用中这样做。

    【讨论】:

    • 是的,我知道我没有在我的问题中使用外键,但在实际代码中我使用了:)。第一次观察帮助了我。不过谢谢!!
    • 除了需要调用[db executeQuery:@"PRAGMA foreign_keys = YES"];而不是 executeUpdate,这总是让我感到困惑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 2014-10-15
    相关资源
    最近更新 更多