iOSでSQLiteを使う
iPhoneアプリを作るときにSQLiteを使うことになり、FMDBというのが便利らしかったので利用してみました。
DBの用意
まず、DBとして使うファイルを指定し、開きます
static NSString* const DB_NAME = @"sample.db"; - (FMDatabase *) connectDB { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *dir = [paths objectAtIndex:0]; NSString *db_path = [dir stringByAppendingPathComponent:DB_NAME]; NSFileManager *fm = [NSFileManager defaultManager]; BOOL success = [fm fileExistsAtPath:db_path]; // DB削除するとき /* if(success){ [fm removeItemAtPath:db_path error:nil]; ALog(@"delete db_file"); success = false; } */ if(!success){ //データベースが存在しなければ、新規作成する success = [fm createFileAtPath:db_path contents:nil attributes:nil]; if(!success){ ALog(@"error in making file"); return NO; } } ALog(@"success : %d, db_path is '%@'", success, db_path ); return [FMDatabase databaseWithPath:db_path]; }
これで
// .hファイルで以下のように宣言してから // @property FMDatabase *db; self.db = [self connectDB];
とかすればOKです。
SQLの適用
SQLiteなので、SQLを書いてDBを操作します。
日時型はないので、REALとかTEXTで定義します。
CREATE TABLE
外部キー制約を有効化します。
// dbに接続 [self.db open]; // トランザクション開始 [self.db beginTransaction]; // 1つ目のsqlで外部キー制約の有効化 // 2つ目のsqlでテーブルが存在しなければusersテーブルを作成する NSArray *initSQLs = @[@"PRAGMA foreign_keys=ON", @"CREATE TABLE if not exists users (id integer primary key autoincrement, name string, created real, modified real)"]; BOOL isSucceeded = YES; // sqlの実行に失敗すればisSucceededをNOにする for(NSString *initSQL in initSQLs) { if(![self.db executeUpdate:initSQL]) { isSucceeded = NO; break; } } if(isSucceeded){ // sqlの実行に成功したらコミット ALog(@"created tables"); [self.db commit]; } else { // sqlの実行に失敗すればロールバック ALog(@"ERROR!!!! fail to insert sample data. now, rollback"); [self.db rollback]; } // dbを閉じる [self.db close];
executeUpdateはトランザクションで実行すること。
SELECT
[self.db open]; // プレースホルダを使う NSString * sql = @"select * from users where id > ? order by modified desc"; // sqlを実行し、結果を取得(FMResultSet型) // カンマ区切りでプレースホルダに入れる値を入れる // int型はNSNumberに変換する FMResultSet *result = [self.db executeQuery:sql, [NSNumber numberWithInt:5]]; NSMutableArray *names = [[NSMutableArray alloc] init]; // nextで次の結果へ行くのでwhile文で回す while ([result next]) { // 結果の中から"name"というカラム名を取得 [names addObject:[result stringForColumn:@"name"]]; } // 結果を入れてたFMResultSetを閉じる [result close]; [self.db close];
executeQueryの時はトランザクションにしなくていい