FMDatabaseQueue中的外键

时间:2014-04-24 11:46:48

标签: objective-c sqlite fmdb

所以我使用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;
}

并且我不认为外键是在队列中启用的,有没有办法如何为队列启用它们,或者我必须在每个查询中执行它?

1 个答案:

答案 0 :(得分:3)

两个观察结果:

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

      

    此pragma是交易中的无操作;只有在没有待处理的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 pragma,则可以:

    [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条目就会失败。在插入book条目之前,我无法插入author条目:

    [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]);
    }];
    
  3. 所以,它的长短不一样,外键可以与FMDatabaseQueue一起正常工作,但我只建议不要在inTransaction调用中做到这一点。