【问题标题】:iOS SQLite Blob data is saving NULLiOS SQLite Blob 数据正在保存 NULL
【发布时间】:2016-08-15 11:02:32
【问题描述】:

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

create table sign(id integer 主键AUTOINCREMENT, image blob,invoiceid integer);

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


}

【问题讨论】:

    标签: ios objective-c sqlite blob nsdata


    【解决方案1】:
    1. 始终检查sqlite3_prepare_v2 的结果。如果失败,请使用sqlite3_errmsg 记录问题。
    2. 只有在sqlite3_prepare_v2 成功时才调用sqlite3_finalize
    3. 您得到了 blob 的 NULL,因为您对 sqlite3_bind_blob 的调用传递了错误的列索引。它应该是1,而不是2,因为您想绑定到INSERT 语句中的第一个?
    4. 为什么不一致?为什么使用stringWithFormat 设置invoiceid 列的值,然后使用sqlite_bind_xxx 设置image 列?你应该绑定两者。切勿使用 stringWithFormat 构建查询。
    5. 您拨打sqlite3_step 两次。只调用一次并在调用之前绑定您的值。
    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));
        }
    }
    

    【讨论】:

    • sqlite3_finalize() 允许在 NULL 语句上调用。
    • @CL。但为什么?您只需要关闭一个打开的数据库。您只需要完成一个准备好的语句。
    • 在某些情况下,无条件调用sqlite3_finalize 会更容易。
    • 谢谢先生,它的工作方式与我想要的完全一样。
    猜你喜欢
    • 2015-06-19
    • 2013-11-02
    • 2011-02-14
    • 1970-01-01
    • 2016-09-13
    • 2012-01-11
    • 2015-11-15
    • 1970-01-01
    • 2014-06-27
    相关资源
    最近更新 更多