所以我使用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;
}
并且我不认为外键是在队列中启用的,有没有办法如何为队列启用它们,或者我必须在每个查询中执行它?
答案 0 :(得分:3)
两个观察结果:
关于使用FMDatabaseQueue
的外键约束的唯一警告是,我建议不要在PRAGMA foreign_keys
事务中使用FMDatabaseQueue
(即在inTransaction
块内) 。 PRAGMA foreign_keys
的{{3}}说:
此pragma是交易中的无操作;只有在没有待处理的
BEGIN
或SAVEPOINT
时,才能启用或禁用外键约束强制执行。
如果你从inDatabase
块内执行此编译指示,那么你会没事的。
您的示例并未说明foreign_keys
的实际效果。外键约束仅在修改数据库中的数据时适用。但您只是SELECT
,因此PRAGMA foreign_keys
的设置无关紧要。
为了说明此pragma的使用,请考虑以下示例。我创建了book
和author
个表,前者有后者的外键:
[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]);
}];
所以,它的长短不一样,外键可以与FMDatabaseQueue
一起正常工作,但我只建议不要在inTransaction
调用中做到这一点。