Two observations:
The only caveat regarding foreign key constraints with
FMDatabaseQueue
is that I would advise against usingPRAGMA foreign_keys
within aFMDatabaseQueue
transaction (i.e. within ainTransaction
block). The documentation forPRAGMA foreign_keys
says:This pragma is a no-op within a transaction; foreign key constraint enforcement may only be enabled or disabled when there is no pending
BEGIN
orSAVEPOINT
.If you do this pragma from within a
inDatabase
block, though, you will be fine.Your example does not illustrate
foreign_keys
in action. Foreign key constraints are only applicable when modifying data in the database. But you're only doingSELECT
, so the setting ofPRAGMA foreign_keys
is irrelevant.To illustrate the use of this pragma, consider the following example. I create
book
andauthor
tables, where the former has a foreign key to the latter:[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]); }];
Without
foreign_keys
pragma, this works:[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]); }];
But if I turn on foreign keys:
[queue inDatabase:^(FMDatabase *db) { // turn on foreign keys success = [db executeUpdate:@"PRAGMA foreign_keys = YES"]; if (!success) NSLog(@"Foreign keys pragma failed: %@", [db lastErrorMessage]); }];
And if try that again, the first insert of the
book
without a correspondingauthor
entry fails. I can't insert thebook
entry until I insert theauthor
entry:[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]); }];
So, the long and short of it, foreign keys work fine with FMDatabaseQueue
, but I would only advise against doing it from within a inTransaction
call.