在数据库中插入和读取BLOB数据的SQLite3

6

我需要读写BLOB数据到数据库中。这是我的表结构:

    #define CREATE_TABLE_USERS_SQL "CREATE TABLE IF NOT EXISTS %@ ( \
UserID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, \
Name VARCHAR(50), \
Image BLOB);"

如何将它插入数据库,然后从中检索出来?

环境:iPhone SDK 4.1 SQLite3 数据库。

这段代码失败了:

        NSData * buf2 = [[NSData alloc] init];
        sqlite3_column_blob(statement, 5);
        buf2 = sqlite3_column_bytes(statement, 5);
        user.image = [UIImage imageWithData: buf2];

这个问题正在询问与你的问题相同的事情,并且那里的答案应该能满足你的需求:https://dev59.com/YnRB5IYBdhLWcg3wXmRI - Brad Larson
5个回答

13

谢谢大家!在你们的帮助下,我解决了问题,并想分享结果,以便将来像我一样的初学者可以参考。)

-(void) addToDB
{
    NSLog(@"\nCreating db");
    NSString *str = @"CREATE TABLE IF NOT EXISTS Images (image1 BLOB);";
    int res = SQLITE_ERROR;


    res = sqlite3_open([@"aa.sql" UTF8String], &database);
    res = sqlite3_exec(database, [str UTF8String], NULL, NULL, NULL);

    sqlite3_stmt *updStmt =nil; 

    const char *sql = "INSERT INTO Images (image1) VALUES (?);";
    res = sqlite3_prepare_v2(database, sql, -1, &updStmt, NULL);

    if(res!= SQLITE_OK)
    {
        NSLog(@"Error while creating update statement:%s", sqlite3_errmsg(database));
    }

    UIImage *img = [UIImage imageNamed: @"flower.png"];
    NSData *imageData = [NSData dataWithData: UIImagePNGRepresentation(img)];

    res = sqlite3_bind_blob(updStmt, 1, [imageData bytes], [imageData length] , SQLITE_TRANSIENT);

    if((res = sqlite3_step(updStmt)) != SQLITE_DONE)
    {
        NSLog(@"Error while updating: %@", sqlite3_errmsg(database));
        sqlite3_reset(updStmt);
    } 

    res = sqlite3_reset(updStmt);
    res = sqlite3_close(database);
}

-(void) readFromDB
{
    NSLog(@"\nReading from db");

    NSString *query = @"SELECT image1 from Images";
    int res = SQLITE_ERROR;
    int len = 0;

    res = sqlite3_open([@"aa.sql" UTF8String], &database);

    sqlite3_stmt *statement;
    res = sqlite3_prepare_v2 (database, [query UTF8String], -1, &statement, nil);

    if (res == SQLITE_OK)
    {
        if (sqlite3_step(statement) == SQLITE_ROW)
        {
            len = sqlite3_column_bytes(statement, 0);
            NSData *imgData = [[NSData alloc] initWithBytes: sqlite3_column_blob(statement, 0) length: len];           


            UIImage *img = [[UIImage alloc] initWithData:imgData];

            self.view1.image = img;

        }
    }
    sqlite3_finalize(statement);

    res = sqlite3_close(database);
}

感谢您的发布,这段代码运行良好。但是当我将图像的名称从“flower.png”更改为其他名称,例如“xyz.png”时,它仍然在ImageView中显示以前的图像。您能指出原因吗? - user885790
也许你需要先去适当的数据库记录,然后再从中读取图像,现在它总是获取第一条记录。尝试一下,我真的不记得了,那是一年前的事了。 - yozhik
在 NSLog(@"创建更新语句时出错:%@", sqlite3_errmsg(database)); 中应该使用 %s 格式化。 - Valeriy Van
常量SQLITE_BLOB在sqlite3_bind_blob调用中被错误使用。应该使用SQLITE_TRANSIENT或SQLITE_STATIC。http://www.sqlite.org/c3ref/bind_blob.html - Valeriy Van
使用SQLITE_TRANSIENT时要小心,根据情况不当使用可能会导致BAD_ACCESS错误。在我遇到问题之前,我一直使用它,直到我将其更改为SQLITE_STATIC。 - garthoid
这是什么编程语言?我没看到它在任何地方列出来。 - user5359531

1
除了选择客户端或编程接口之外,使用与任何其他字符串字段没有区别。
[更新] 我还没有开发iPhone的运气,但我相信它与任何其他SELECT或INSERT查询相同。确保对BLOB进行编码并用单引号(')像字符串一样括起来。

0

0

//-----插入图片

  - (void)setImage:(UIImage *)theImage
 {

  if(sqlite3_open([databasePath UTF8String],&myDatabase)==SQLITE_OK)
  {    
    NSString *insertProgrammeSql = @"INSERT INTO imageTable (imageName) VALUES (?)";

sqlite3_stmt *statement;

   if (sqlite3_prepare_v2(myDatabase, [insertProgrammeSql cStringUsingEncoding:NSUTF8StringEncoding], -1, &statement, NULL) == SQLITE_OK) {

    NSData *imageData = UIImagePNGRepresentation(theImage);

         sqlite3_bind_blob(statement, 1, [imageData bytes], [imageData length], SQLITE_TRANSIENT);

    sqlite3_step(statement);
}
  sqlite3_close(myDatabase);
//  return YES;    
}   


  }

//--------获取图片

   -(UIImage *)getImage

    {

    UIImage *image = nil;


if(sqlite3_open([databasePath UTF8String],&myDatabase)==SQLITE_OK)
{   

NSString *selectSql = @"SELECT image FROM imageTable";

sqlite3_stmt *statement;
if (sqlite3_prepare_v2(myDatabase, [selectSql UTF8String], -1, &statement, NULL) == SQLITE_OK)
{
    int length = sqlite3_column_bytes(statement, 0);
    NSData *imageData = [NSData dataWithBytes:sqlite3_column_blob(statement, 0 ) length:length];

    image = [UIImage imageWithData:imageData];



  sqlite3_finalize(statement);

  }
     sqlite3_close(myDatabase);
  }
 return image;
 }

0

This code fails:

   NSData * buf2 = [[NSData alloc] init];
   sqlite3_column_blob(statement, 5);
   buf2 = sqlite3_column_bytes(statement, 5);
   user.image = [UIImage imageWithData: buf2];

您正在按正确的顺序调用SQLite函数。根据SQLite文档:

最安全、最容易记忆的策略是以以下方式之一调用这些例程:

  • sqlite3_column_text() 后跟 sqlite3_column_bytes()
  • sqlite3_column_blob() 后跟 sqlite3_column_bytes()
  • sqlite3_column_text16() 后跟 sqlite3_column_bytes16()

换句话说,您应该首先调用sqlite3_column_text()、sqlite3_column_blob()或sqlite3_column_text16()将结果强制转换为所需格式,然后调用sqlite3_column_bytes()或sqlite3_column_bytes16()查找结果的大小。不要混合调用sqlite3_column_text()或sqlite3_column_blob()与调用sqlite3_column_bytes16(),也不要混合调用sqlite3_column_text16()与调用sqlite3_column_bytes()。

但是,buff2 是一个整数,而不是数据指针。 sqlite3_column_bytes 告诉您 blob 中有多少字节。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接