何回かエントリーが分かれそうな気がしたので。
やっとできたINSERT文の方法について書いていきたいと思います。
と同時に、CREATE文やオープン、クローズの作業をメソッド化させて、前回よりも、綺麗に整いました。
//TestTable.h
#import <Foundation/Foundation.h> #import <sqlite3.h> @interface TestTable : NSObject { sqlite3 *db; NSString *dbPath; } @property sqlite3 *db; @property (retain,nonatomic) NSString *dbPath; -(id)init; -(BOOL)openDataBase; -(BOOL)createTable; -(BOOL)insertData; -(void)closeDataBase; -(void)errDataBase; @end |
//TestTable.m
#import "TestTable.h" @implementation TestTable @synthesize db; @synthesize dbPath; -(id)init{ self = [super init]; //dbが存在しているかどうかの確認 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); dbPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"test.db"]; //ファイルが存在しない場合 if (![[NSFileManager defaultManager] fileExistsAtPath:dbPath]) { //ファイルを作成する BOOL result = [[NSFileManager defaultManager] createFileAtPath:dbPath contents:nil attributes:nil]; //ファイル作成が失敗した場合 if (!result) { } //BOOL sql_exec_ok = NO; //sqliteをオープンする if([self openDataBase]){ //テーブルの作成 if ([self createTable]) { if([self insertData]){ NSLog(@"正常終了しました。"); } }; //テーブルのクローズ [self closeDataBase]; } } return self; } //sqliteをオープンする -(BOOL)openDataBase{ int ret; ret = sqlite3_open([dbPath UTF8String],&db); //正常終了 if(ret == SQLITE_OK){ return YES; //異常終了 }else { //エラーが発生してしまったので、クローズを行う sqlite3_close(db); return NO; } } //tableの作成 -(BOOL)createTable{ //sqlの設定 char *sql = "CREATE TABLE test(column_no1,column_no2)"; //各関数の戻り値 int ret; //sql文を実行するための変数 sqlite3_stmt *sqlstmt; ret = sqlite3_prepare_v2(db,sql,-1,&sqlstmt,NULL); //実行準備おk if(ret == SQLITE_OK){ //sqlの実行を行う ret = sqlite3_step(sqlstmt); //sql文の解放 sqlite3_finalize(sqlstmt); //sqlの実行が正常終了した場合 if(ret == SQLITE_DONE){ return YES; } } //エラーメセッドをコール [self errDataBase]; //dbクローズ [self closeDataBase]; return NO; } -(BOOL)insertData{ BOOL q_Ret = NO; //各関数の戻り値 int ret; //トランザクションの開始 sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL); //insert文の作成 char *sql = "insert into test(column_no1,column_no2)values('こんばんわ','abcdef')"; ret = sqlite3_exec(db, sql, NULL, NULL, NULL); //正常終了(COMMITをして処理を終了) if(ret == SQLITE_OK){ //COMMIT sqlite3_exec(db, "COMMIT TRANSACTION", NULL, NULL, NULL); q_Ret = YES; //異常終了(ROLLBACKして処理を終了) }else { //エラーメセッドをコール [self errDataBase]; //ROLLBACK sqlite3_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, NULL); } return q_Ret; } //sqliteをクローズする -(void)closeDataBase{ sqlite3_close(db); } //sqliteのエラー処理 -(void)errDataBase{ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[[NSString alloc] initWithFormat:@"error:%d",sqlite3_errcode(db)] message:[[NSString alloc] initWithUTF8String:sqlite3_errmsg(db)] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil ]; [alertView show]; [alertView release]; } @end |
それぞれのメソッドは、
openDataBaseメソッド:dbのオープン
closeDataBaseメソッド:dbのクローズ
errDataBaseメソッド:エラーメッセージをアラートで表示
createTableメソッド:TABLEの作成
insertDataメソッド:TABLEにデータを登録する
です。
twitterでもつぶやきましたが、トランザクションの書き方に時間をくいました。
こうして各作業をメソッド化することで汎用性が高まるのかなと。
ただ気に食わない部分もあり、特にINSERT文のvalues以降を動的に変更することがこの書き方ではできないこと。
for文でまわしながらそういった作業をすることが多いんだけど。もっと改良する点があるのかなと。
後、CREATE文を実行する時も、カラム名やテーブル名を直指定してしまっていること。
引数を元に、動的にTABLEを作りたい場合などには、融通が利かない。
もっと汎用的に変えていきたいと思います。
実行した結果についてですが、正常終了しました。
(ターミナルでも確認済み)
参考:
rktSQLite2:トランザクションの操作
SQLite Tutorial - Adding data
0 コメント:
コメントを投稿