2016-04-22 15 views
0

このコードを使用してSignatureViewのBLOBデータを挿入しようとしていますが、実際にデータベースを参照するとデータの代わりにnullがあります。 私の署名テーブルのスキーマを以下に示します。iOS SQLite BlobデータがNULLを保存しています

create table sign(ID整数主キーAUTOINCREMENT、イメージblob、invoiceid整数)。

-(void)storeImageData:(NSData *)imageData withInvoiceID:(NSInteger)invoiceID{ 

    NSString *dbPath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:@"database.sqlite3"]; 
    const char *dbpath = [dbPath UTF8String]; 
    sqlite3 *contactDB; 

    sqlite3_stmt *statement; 

    NSLog(@"%@",dbPath); 
    if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK) 
    { 
     int invoiceIDINT = (int)invoiceID; 
    // 
     NSString *insertSQL = [NSString stringWithFormat: @"INSERT INTO sign (image,invoiceid) VALUES (?,%d)", invoiceIDINT]; 

     const char *insert_stmt = [insertSQL UTF8String]; 

     sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL); 
     if (sqlite3_step(statement) == SQLITE_DONE) 
     { 
      sqlite3_bind_blob(statement, 2, [imageData bytes], [imageData length], SQLITE_TRANSIENT); 
      sqlite3_step(statement); 

     } else { 
      const char *Error = sqlite3_errmsg(database); 
      NSString *error = [[NSString alloc]initWithUTF8String:Error]; 
      UIAlertView *view = [[UIAlertView alloc]initWithTitle:@"Error2" message:[NSString stringWithFormat:@"Last inserted ID: %@",error] delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil]; 
      [view show]; 
     } 
     sqlite3_finalize(statement); 
     sqlite3_close(contactDB); 
    } 


} 

答えて

2
  1. 必ずsqlite3_prepare_v2の結果を確認してください。失敗した場合は、sqlite3_errmsgを使用して問題を記録してください。
  2. sqlite3_prepare_v2が成功した場合にのみ、sqlite3_finalizeを呼び出します。
  3. sqlite3_bind_blobへの呼び出しが誤った列インデックスを渡しているため、BLOBにはNULLが返されます。 INSERTステートメントの最初の?にバインドしたいので、1で、2ではないはずです。
  4. なぜ矛盾しますか? stringWithFormatを使用してinvoiceid列の値を設定し、列にsqlite_bind_xxxを使用するのはなぜですか?両方をバインドする必要があります。クエリを作成するのに、stringWithFormatを使用しないでください。
  5. sqlite3_stepを2回呼び出します。それを一度呼び出すと、それを呼び出す前に値をバインドするだけです。
  6. あなたのアプリケーションのリソースバンドル内のデータベースに書き込んでいるようです。あなたは実際のデバイスでそれを行うことはできません。これはシミュレータでは動作しますが、実際のiOSデバイスでは動作しません。データベースファイルをDocumentsフォルダに配置する必要があります。上記のすべてを考慮する

は、あなたのコードは次のようなものでなければなりません:

-(void)storeImageData:(NSData *)imageData withInvoiceID:(NSInteger)invoiceID{ 
    // This is wrong - you need to update this to use the Documents folder 
    NSString *dbPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"database.sqlite3"]; 
    const char *dbpath = [dbPath UTF8String]; 
    NSLog(@"%@",dbPath); 

    sqlite3 *contactDB; 
    if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK) 
    { 
     const char *insert_stmt = "INSERT INTO sign (image, invoiceid) VALUES (?, ?)"; 

     sqlite3_stmt *statement; 
     if (sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL) == SQLITE_OK) { 
      sqlite3_bind_blob(statement, 1, [imageData bytes], [imageData length], SQLITE_TRANSIENT); 
      sqlite3_bind_int(statement, 2, (int)invoiceID); 

      if (sqlite3_step(statement) == SQLITE_DONE) { 
       // Row inserted successfully 
      } else { 
       const char *Error = sqlite3_errmsg(contactDB); 
       NSString *error = [[NSString alloc] initWithUTF8String:Error]; 
       UIAlertView *view = [[UIAlertView alloc] initWithTitle:@"Error2" message:[NSString stringWithFormat:@"Last inserted ID: %@",error] delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil]; 
       [view show]; 
      } 

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

     sqlite3_close(contactDB); 
    } else { 
     NSLog(@"Unable to open database at path %@: %s", dbPath, sqlite3_errmsg(contactDB)); 
    } 
} 
+0

'sqlite3_finalize()' NULL文で呼ばれるように許可されています。 –

+1

@CL。しかし、なぜ?開いているデータベースを閉じるだけで済みます。あなたは、準備されたステートメントを完成する必要があります。 – rmaddy

+0

無条件に 'sqlite3_finalize'を呼び出す方が簡単な場合があります。 –

関連する問題