2016-04-30 14 views
0

NSMutableStringをsqliteに挿入できませんでした。 Webサーバーから情報を取得して正常にsqliteファイルを作成しましたが、Webからsqliteにデータを挿入できませんでした。Objective-Cでsqliteに文字列を挿入するにはどうすればよいですか?

ここに問題があると思います。

NSString *insertSQL = @"INSERT INTO Questions VALUES (result)"; 

しかし、私はこの問題を解決できませんでした。誰でも私を助けてくれますか?

- (void)getInforamtionFromWeb { 
    NSURL *url = [NSURL URLWithString:kGetUrl]; 
    data = [NSData dataWithContentsOfURL:url]; 
    NSError *error; 
    json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; 
    result = [[NSMutableString alloc] init]; 
    for (NSObject * obj in json) 
    { 
     [result appendString:[obj description]]; 
    } 
} 

-(void)initiatSqlite{ 
    // Get the documents directory 
    dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    docsDir = dirPaths[0]; 
    // Build the path to the database file 
    _databasePath = [[NSString alloc] 
        initWithString: [docsDir stringByAppendingPathComponent: 
             @"Questions.db"]]; 
    NSFileManager *filemgr = [NSFileManager defaultManager]; 
    if ([filemgr fileExistsAtPath: _databasePath ] == NO) 
    { 
     const char *dbpath = [_databasePath UTF8String]; 
     if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK) 
     { 
      char *errMsg; 
      const char *sql_stmt = 
      "CREATE TABLE IF NOT EXISTS Questions (ID INTEGER PRIMARY KEY AUTOINCREMENT, Question Text, AnswerA Text, AnswerB Text, AnswerC Text, AnswerD Text, CorrectAnswer Text, Explanation Text)"; 
      if (sqlite3_exec(_contactDB, sql_stmt, NULL, NULL, &errMsg) != SQLITE_OK) 
      { 
       [self Worningtitle:@"Error" Message:@"Failed to create table"]; 
      } 
      sqlite3_close(_contactDB); 
     } else { 
      [self Worningtitle:@"Error" Message:@"Failed to open/create database"]; 

     } 
    } 

} 
- (void) insertData 
{ 
    sqlite3_stmt *statement; 
    const char *dbpath = [_databasePath UTF8String]; 


    if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK) 
    { 
     NSString *insertSQL = @"INSERT INTO Questions VALUES (result)"; 

     const char *insert_stmt = [insertSQL UTF8String]; 
     NSLog(@"%s",insert_stmt); 
     sqlite3_prepare_v2(_contactDB, insert_stmt, -1, &statement, NULL); 
     sqlite3_bind_text(statement, 1, [result UTF8String], -1, SQLITE_TRANSIENT); 

     if (sqlite3_step(statement) == SQLITE_DONE) 
     { 
      NSLog(@"Product added"); 
     } else { 
      NSLog(@"Failed to add Product"); 
     } 

     sqlite3_finalize(statement); 
     sqlite3_close(_contactDB); 
    } 
} 

答えて

1

あなたは正しいです。 INSERTステートメントが正しくありません。それはする必要があります:sqlite3_bind_xxxが適用される場所

NSString *insertSQL = @"INSERT INTO Questions VALUES (?)"; 

?です。

Questionsテーブルには多くの列がありますが、1つの値しか挿入していないことに注意してください。値を挿入する列を指定する必要があります。例:

NSString *insertSQL = @"INSERT INTO Questions (Question) VALUES (?)"; 

あなたresult値に配置する必要があり、適切な列名でQuestionを置き換えところで

- あなたのコードは、それを改善するために多くの作業が必要。特にsqlite3_prepare_v2を使用すると、さらに多くのエラーチェックを追加する必要があります。より多くのデータを挿入したいに基づいて

、あなたはこのような何かをするだろう:

- (BOOL)insertData { 
    BOOL result = NO; // failed 
    const char *dbpath = [_databasePath UTF8String]; 
    if (sqlite3_open(dbpath, &_contactDB) == SQLITE_OK) { 
     const char *insert_stmt = "INSERT INTO Questions(AnswerA,AnswerB,AnswerC,AnswerD,CorrectAnswer,Question) VALUES (?,?,?,?,?,?)"; 
     sqlite3_stmt *statement; 

     if (sqlite3_prepare_v2(_contactDB, insert_stmt, -1, &statement, NULL) == SQLITE_OK) { 
      sqlite3_bind_text(statement, 1, [answerA UTF8String], -1, SQLITE_TRANSIENT); 
      sqlite3_bind_text(statement, 2, [answerB UTF8String], -1, SQLITE_TRANSIENT); 
      sqlite3_bind_text(statement, 3, [answerC UTF8String], -1, SQLITE_TRANSIENT); 
      sqlite3_bind_text(statement, 4, [answerD UTF8String], -1, SQLITE_TRANSIENT); 
      sqlite3_bind_text(statement, 5, [correctAnswer UTF8String], -1, SQLITE_TRANSIENT); 
      sqlite3_bind_text(statement, 6, [question UTF8String], -1, SQLITE_TRANSIENT); 

      if (sqlite3_step(statement) == SQLITE_DONE) { 
       NSLog(@"Product added"); 
       result = YES; 
      } else { 
       NSLog(@"Failed to add Product: %s", sqlite3_errmsg(_contactDB)); 
      } 

      sqlite3_finalize(statement); 
     } else { 
      NSLog(@"Unable to prepare statement: %s", sqlite3_errmsg(_contactDB); 
     } 

     sqlite3_close(_contactDB); 
    } else { 
     NSLog(@"Unable to open database: %@", sqlite3_errmsg(_contactDB)); 
    } 

    return result; 
} 

あなたはデータが含まれている実際の変数/値を参照してsqlite3_bind_text通話のそれぞれを更新する必要があることに注意してください各列について。

IDの値をバインドする必要はありません。自動設定するように設定されているためです。

すべての適切なエラーチェックに注意してください。私もそれを作ったinsertDataは、データが正常に追加されたかどうかを示すBOOLを返します。

+0

大変ありがとうございます。文字列は、以下よりもはるかに多く、次にこれをsqliteに挿入しますか? { AnswerA =まだ、 AnswerB = Gh; AnswerC = Gf; AnswerD = Gh; CorrectAnswer = D; 説明= "説明:まだ"; ID = 35; 質問= Ty; } 2016-04-30 00:22:27929 Pharm Tech [9960:824218] { AnswerA =まだ、 AnswerB = Gh; AnswerC = Gf; AnswerD = Gh; CorrectAnswer = D; 説明= "説明:まだ"; ID = 35; 質問= Ty; } { AnswerA = Gf; AnswerB = Gh; Answer –

+0

各列に対して、INSERT文の最初の括弧セットに列名を追加し、2番目の括弧セットに '?'を追加し、データ型に対応する 'sqlite3_bind_xxx'を呼び出します。 – rmaddy

+0

私はこれをしました。次は、私はたくさん試しました。手伝ってくれませんか? NSString * insertSQL * @ "INSERT INTOの質問(AnswerA、AnswerB、AnswerC、AnswerD、CorrectAnswer、ID、質問)VALUES(?)"; ' 'const char * insert_stmt = [insertSQL UTF8String];' ' NSLog (ステートメント、1、[結果UTF8String]、-1、SQLITE_TRANSIENT); ' –

0

は、すべてのテーブルに共通の方法を作る聞く:キーと辞書内の値など、すべての値として パスのすべてのフィールド名:

+(BOOL)insertWithReturnConfirmInTable:(NSString *)tableName Param:(NSDictionary *)params 
{ 
     NSArray *keys = [[NSArray alloc] initWithArray:[self GetColumnsForTable:tableName]]; 

     //insert statement 
     NSString *query = [NSString stringWithFormat:@"INSERT INTO %@(",tableName]; 

     //set keys 
     for (int i=0; i<[keys count]; i++) { 
      if([keys objectAtIndex:i] == [keys lastObject]) 
      { 
       query = [query stringByAppendingString:[NSString stringWithFormat:@"%@) VALUES (",[keys objectAtIndex:i]]]; 
       for (int m=0; m<[keys count]; m++) { 

        if([keys objectAtIndex:m] == [keys lastObject]) 
         query = [query stringByAppendingString:@"?)"]; 
        else 
         query = [query stringByAppendingString:@"?,"]; 
       } 
      } 
      else 
      { 
       query = [query stringByAppendingString:[NSString stringWithFormat:@"%@,",[keys objectAtIndex:i]]]; 
      } 
     } 
     NSLog(@"Query : %@",query); 

     if (sqlite3_open([[self getDBPath] UTF8String], &dbObj) == SQLITE_OK) { 

      sqlite3_stmt *addStmt = nil; 

      if (sqlite3_prepare_v2(dbObj, [query UTF8String], -1, &addStmt, NULL) != SQLITE_OK) 
       NSAssert1(0, @"Error while creating insert statement. '%s'",sqlite3_errmsg(dbObj)); 

      //for Values 
      for (int i=0; i<[keys count]; i++) { 
       sqlite3_bind_text(addStmt, i+1, [[NSString stringWithFormat:@"%@",[params objectForKey:[keys objectAtIndex:i]]] UTF8String], -1, SQLITE_TRANSIENT); 
      } 

      if (SQLITE_DONE != sqlite3_step(addStmt)) { 
       NSLog(@"Error while inserting data. '%s'", sqlite3_errmsg(dbObj)); 
       sqlite3_close(dbObj); 
       return NO; 
      } 
      else { 
       sqlite3_finalize(addStmt); 
       NSLog(@"data inserted in table : %@",tableName); 
       sqlite3_close(dbObj); 
       return YES; 
      } 


     } else { 
      NSLog(@"Error in opening database."); 
      sqlite3_close(dbObj); 
      return NO; 
     } 

    } 
} 

呼び出し方法。テーブル名を渡します。

NSDictionary *param = [[NSDictionary alloc]initWithObjectsAndKeys:@"1",@"S_Id",@"abc",@"Name", nil]; 
[database insertInTable:@"Child" Param:param]; 
+0

1) 'query'には' NSMutableString'を使います。 'stringByAppendingString'を使用するよりもずっと優れています。 2) 'sqlite3_close'をなぜ3回呼び出すのですか?正しい場所に置いて1つの 'return'ステートメントがあれば、1だけ必要です。 3) 'sqlite3_step'呼び出しが失敗した場合、準備されたステートメントを確定していません。 4)あなたは 'sqlite3_errmsg'をログする必要があります。 – rmaddy

+0

5) 'sqlite3_bind_text'呼び出しで' stringWithFormat'を使うのは悪い考えです。文字列には必要ないので、他の型には使用しないでください。 6)このコードは、すべての列がテキストであることを前提としています。だから、これは良い一般的なアプローチではありません。 – rmaddy

+0

rmaddyに感謝の意を表します。しかし、我々はその時にsqlite3_open sqlite3_closeです。そうでない場合は、その時点で複数の操作を使用すると問題が発生する可能性があります。 –

関連する問題