sqliteではデフォルトで外部キーが無効になっているという事実に出くわしました。「on delete casdade」外部キーがあり、親テーブル レコードを削除しても子レコードは削除されません。さまざまな投稿は、接続ごとに「PRAGMAforeign_keys = ON;」を有効にする必要があることを示しています。では、FMDatabase のどこで有効にするのでしょうか? 各 SQL stmt の前にコマンドを実行する代わりに、何らかの設定を行うことをお勧めします。PS。FMDatabaseQueue を使用しています。
2707 次
4 に答える
8
私はすぐにチェックしPRAGMA foreign_keys = ON;
、5.1 シミュレーターと 5.1 iPod Touch の両方で問題なく動作しました。ccgus が示唆するように、データベース接続をキャッシュする必要があります。キューを使用する場合は、データベースを使用する必要があるたびに新しいキューが作成されないように、キューをキャッシュしてコードを再編成するだけです。あなたの現在のアプローチでは、実際には使用せずに毎回新しいキューを作成する場合、キューを持つ意味は何ですか?
質問に戻りますが、ご存知のように、外部キーはデフォルトでオフになっているため、最初に有効にする必要があります。私はなんとかそれを行うことができましたPRAGMA foreign_keys = ON;
.ここに私が使用したテストコードのいくつかがあります:
//create database
NSString* dbPath = [(NSArray*)NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
dbPath = [dbPath stringByAppendingPathComponent:@"test.db"];
db = [FMDatabase databaseWithPath:dbPath];
if ([db open]) {
NSLog(@"Database %@ opened", dbPath);
//check for foreign_key
NSString* sql = @"PRAGMA foreign_keys";
FMResultSet *rs = [db executeQuery:sql];
int enabled;
if ([rs next]) {
enabled = [rs intForColumnIndex:0];
}
[rs close];
if (!enabled) {
// enable foreign_key
sql = @"PRAGMA foreign_keys = ON;";
[db executeUpdate:sql];
// check if successful
sql = @"PRAGMA foreign_keys";
FMResultSet *rs = [db executeQuery:sql];
if ([rs next]) {
enabled = [rs intForColumnIndex:0];
}
[rs close];
}
// do your stuff here, or just cache the connection
} else {
NSLog(@"Failed to open %@", dbPath);
}
かなり単純に見えますが、頭に浮かぶのはexecuteQuery
の代わりにを使用したことだけですexecuteUpdate
。
于 2012-05-08T11:11:54.560 に答える
1
各ステートメントの前に実行する必要があるのはなぜですか? データベースを開き、プラグマを実行し、後で使用するために接続をキャッシュするだけです (とにかくこれを行う必要があります)。
于 2012-05-07T23:55:31.913 に答える