我想使用此查询存储带有图像的数据,所有内容都正确更新但图像列始终为null.i不知道此查询中有什么问题。请任何人帮我修复它。我很新到iOS和sqlite。
UIImage *uiimg = img.image;
NSData *data = UIImagePNGRepresentation(uiimg);
NSString *cmd = [NSString stringWithFormat:@"update APPUSERS set name = '%@', u_name = '%@', contact_no = '%@', address = '%@', dob = '%@', pswrd = '%@', confirm_pswrd = '%@', img = '%d' where u_name ='%@'",name.text, uname.text, pnoneno.text, address.text, dob.text, password.text, confirmpassword.text, data, tempstore] ;
const char * sql = [cmd UTF8String];
if (sqlite3_step(update_statement) == SQLITE_DONE)
{
NSLog(@"success");
}
else
{
NSLog(@"failed");
}
答案 0 :(得分:4)
有关如何使用sqlite3_bind_blob
将NSData
存储在数据库中的示例,请参阅https://stackoverflow.com/a/17994313/1271826。
此外,您绝对应该避免使用stringWithFormat
来构建SQL语句。如果地址为123 O'Brian Way
或Martha's Vineyard
,该怎么办?那个撇号会过早地终止你要插入的字符串。当你去插入Jimmy "The Greek" Snyder
或Dwayne "The Rock" Johnson
时,双引号并不是更好。更糟糕的是,恶意用户可能会对SQL注入造成严重破坏。
您应该使用?
占位符和sqlite3_bind_blob
功能NSData
。对于您的字符串,请使用sqlite3_bind_text
。
因此:
UIImage *uiimg = img.image;
NSData *data = UIImagePNGRepresentation(uiimg);
const char *sql = "update APPUSERS set name = ?, u_name = ?, contact_no = ?, address = ?, dob = ?, pswrd = ?, confirm_pswrd = ?, img = ? where u_name =?";
if (sqlite3_prepare_v2(database, sql, -1, &update_statement, NULL) != SQLITE_OK)
NSLog(@"prepare failed: %s", sqlite3_errmsg(database));
if (sqlite3_bind_text(update_statement, 1, [name.text UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"bind 1 failed: %s", sqlite3_errmsg(database));
if (sqlite3_bind_text(update_statement, 2, [uname.text UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"bind 2 failed: %s", sqlite3_errmsg(database));
if (sqlite3_bind_text(update_statement, 3, [pnoneno.text UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"bind 3 failed: %s", sqlite3_errmsg(database));
if (sqlite3_bind_text(update_statement, 4, [address.text UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"bind 4 failed: %s", sqlite3_errmsg(database));
if (sqlite3_bind_text(update_statement, 5, [dob.text UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"bind 5 failed: %s", sqlite3_errmsg(database));
if (sqlite3_bind_text(update_statement, 6, [password.text UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"bind 6 failed: %s", sqlite3_errmsg(database));
if (sqlite3_bind_text(update_statement, 7, [confirmpassword.text UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"bind 7 failed: %s", sqlite3_errmsg(database));
// note, use blob here
if (sqlite3_bind_blob(update_statement, 8, [data bytes], [data length], SQLITE_TRANSIENT) != SQLITE_OK)
NSLog(@"bind 8 failed: %s", sqlite3_errmsg(database));
if (sqlite3_bind_text(update_statement, 9, [tempstore UTF8String], -1, NULL) != SQLITE_OK)
NSLog(@"bind 9 failed: %s", sqlite3_errmsg(database));
if (sqlite3_step(update_statement) == SQLITE_DONE)
{
NSLog(@"success");
}
else
{
NSLog(@"failed: %s", sqlite3_errmsg(database));
}
sqlite3_finalize(update_statement);
注意,除了sqlite3_bind_xxx
之外,我还建议(a)不要忘记先sqlite3_prepare_v2
; (b)在任何错误上,查看sqlite3_errmsg
; (c)记得在最后做sqlite3_finalize
以释放你的记忆。
但请注意,SQLite在存储大型blob方面效率低下。如果图像是小缩略图,则不是问题,但对于大图像,您应该将图像保存到Documents
文件夹,然后只保存数据库中的文件路径。
最后请注意,如果您有一个加载到UIImage
的图像,然后通过UIImagePNGRepresentation
重新检索,则可能导致数据丢失或文件可能会变得更大。这取决于图像的原始来源。人们通常认为,如果他们UIImagePNGRepresentation
,他们保证得到相同的图像,虽然它看起来几乎相同,但它可以在过程中改变(并不总是;它取决于)。如果您有权访问用于设置NSData
的原始资产/文件/ UIImage
,那么您应该再次参考。
作为一个无关的方面,你真的不应该在数据库中以明文形式存储密码。您应该加密它们或使用keychain来存储密码。
答案 1 :(得分:1)
尝试通过在NSFileManager中创建NSDocument来保存数据库中的图像名称和图像文件夹中的图像。这些是单例实例。您可以将图像保存在与应用程序文档相关的手机记忆文件夹中