iOS SQLite Blob数据保存为NULL

时间:2016-04-22 01:34:30

标签: ios objective-c sqlite blob nsdata

我正在尝试使用此代码插入SignatureView的BLOB数据,但是当我实际浏览数据库时,存在null而不是数据。 我的签名表模式如下所示。

  

创建表格符号(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);
    }


}

1 个答案:

答案 0 :(得分:2)

  1. 请务必检查sqlite3_prepare_v2的结果。如果失败,请使用sqlite3_errmsg
  2. 记录问题
  3. 如果sqlite3_finalize成功,则只能致电sqlite3_prepare_v2
  4. 您获得了NULL blob,因为您对sqlite3_bind_blob的调用传递了错误的列索引。它应该是1,而不是2,因为您希望绑定到?语句中的第一个INSERT
  5. 为什么不一致?为什么使用stringWithFormat设置invoiceid列的值,然后将sqlite_bind_xxx用于image列?你应该绑定两者。切勿使用stringWithFormat来构建查询。
  6. 您拨打sqlite3_step两次。只需调用一次并在调用之前绑定您的值。
  7. 您似乎正在写入应用资源包中的数据库。你不能在真实设备上这样做。它适用于模拟器,但不适用于真正的iOS设备。您需要将数据库文件放在Documents文件夹中。
  8. 考虑到上述所有情况,您的代码应该是这样的:

    -(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));
        }
    }