【问题标题】:iOS - using sqlite database update data not workingiOS - 使用 sqlite 数据库更新数据不起作用
【发布时间】:2013-09-13 20:11:04
【问题描述】:

我想更新 Xcode sqlite db 中的一些数据。 db连接成功,但是sql语句好像有问题,一直返回“添加联系人失败”,谢谢帮助。

- (void) saveData:(id)sender
{

    NSLog(@"The code runs through here!");
    sqlite3_stmt    *statement;

    NSString *documents = [self applicationDocumentsDirectory];
    NSString *dbPath = [documents stringByAppendingPathComponent:@"monitorDB.sqlite"];
    const char *dbpath = [dbPath cStringUsingEncoding:NSASCIIStringEncoding];

    if (sqlite3_open(dbpath, & contactDB) == SQLITE_OK)
    {

        NSString *insertSQL = [NSString stringWithFormat:
                               @"UPDATE profile SET username = \"%@\" WHERE id = 1" ,
                               self.username.text];

        const char *insert_stmt = [insertSQL UTF8String];
        sqlite3_prepare_v2(contactDB, insert_stmt,
                           -1, &statement, NULL);
        if (sqlite3_step(statement) == SQLITE_DONE)
        {
            self.settingStatus.text = @"Contact added";
        } else {
            self.settingStatus.text = @"Failed to add contact";
        }
        sqlite3_finalize(statement);
        sqlite3_close(contactDB);
    }   else {
        self.settingStatus.text = @"DB Not Connect";
    }



}

【问题讨论】:

  • 又一个不使用他们正在使用的API提供的错误报告机制的程序员;提示sqlite3_errmsg().
  • NSAssert1(0, @"创建更新语句时出错。'%s'", sqlite3_errmsg(contactDB));
  • 它没有显示任何消息
  • NSLog() 有什么问题?你为什么使用NSAssert()?断言是测试开发者断言,而不是报告运行时错误。
  • 在尝试使用它之前,您是否将数据库从应用程序包复制到文档文件夹中(当然是测试它不存在)?

标签: iphone objective-c sqlite ios5 ios6


【解决方案1】:

像这样试试..

在 viewdidload 中,我们需要检查表是否存在。如果没有,我们需要创建 db。

NSString *docsdir;
NSArray *dirpaths;

dirpaths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsdir=[dirpaths objectAtIndex:0];
dabasePath=[NSString stringWithFormat:[docsdir stringByAppendingPathComponent:@"contact.db"]];

NSFileManager *filemgr= [NSFileManager defaultManager];
if ([filemgr fileExistsAtPath:dabasePath]==NO ) {
    const char *dbpath=[dabasePath UTF8String];
    if (sqlite3_open(dbpath, &contactDB)== SQLITE_OK) {
        char *error;
        const char *sql_stmt="CREATE TABLE IF NOT EXISTS CONTACTS (ID INTEGER PRIMARY KEY AUTOINCREMENT, ADDRESS TEXT, NAME TEXT, PHONE TEXT, IMAGE BLOB)";
        if (sqlite3_exec(contactDB, sql_stmt, NULL, NULL, &error)!= SQLITE_OK) {
            status.text=@"failed to create";
        }
        sqlite3_close(contactDB);
    }
}

要保存数据,请尝试使用以下代码。

-(IBAction)saveData:(id)sender{

    sqlite3_stmt *statement;
    const char *dbpath = [dabasePath UTF8String];
    NSData *imagedata=UIImagePNGRepresentation(imageview.image);
    if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK) {
        NSString *insertSql =[NSString stringWithFormat:@"INSERT INTO CONTACTS (name, address, phone, image) VALUES (\"%@\", \"%@\", \"%@\", ?) ", name.text, address.text, phone.text ];
        // NSString *nam=name.text;
        const char *insert_stmt = [insertSql UTF8String];
        sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL);
        sqlite3_bind_blob(statement, 1, [imagedata bytes], [imagedata length], NULL);

        if (sqlite3_step(statement) == SQLITE_DONE) {
          status.text=@"contact added";
          [self clearClick:nil];
        }else{
          status.text=@"failed to added";
        }
        sqlite3_finalize(statement);
        sqlite3_close(contactDB);
    }
}

要更新数据,请尝试使用以下代码。

-(IBAction)updateClick:(id)sender{

sqlite3_stmt *updateStmt;
 const char *dbpath = [dabasePath UTF8String];
if(sqlite3_open(dbpath, &contactDB) == SQLITE_OK)
{
    const char *sql = "update contacts Set address = ?, phone = ?, image = ? Where name=?";
    if(sqlite3_prepare_v2(contactDB, sql, -1, &updateStmt, NULL)==SQLITE_OK){
        sqlite3_bind_text(updateStmt, 4, [name.text UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(updateStmt, 1, [address.text UTF8String], -1, SQLITE_TRANSIENT);
        sqlite3_bind_text(updateStmt, 2, [phone.text UTF8String], -1, SQLITE_TRANSIENT);
        NSData *imagedata=UIImagePNGRepresentation(imageview.image);
        sqlite3_bind_blob(updateStmt, 3, [imagedata bytes], [imagedata length], NULL);
    }
}
char* errmsg;
sqlite3_exec(contactDB, "COMMIT", NULL, NULL, &errmsg);

if(SQLITE_DONE != sqlite3_step(updateStmt)){
    NSLog(@"Error while updating. %s", sqlite3_errmsg(contactDB));
}
else{
    [self clearClick:nil];
}
sqlite3_finalize(updateStmt);
sqlite3_close(contactDB);
}

【讨论】:

  • 在与数据库进行任何交易之前,请确保您将数据库从捆绑包复制到文档目录(以防目录中不存在)
  • 非常感谢 kalyani puvvada。过去一个月我一直在为更新查询而苦苦挣扎。即使我看到了你的回答,我也没有完全使用代码。刚刚我完全实现了你的更新代码。它现在可以工作了对我来说。我现在很开心。谢谢。
【解决方案2】:

检查您的 sql 查询并像这样更改它。

NSString *insertSQL = [NSString stringWithFormat:
                           @"UPDATE profile SET username = '%@' WHERE id = 1" ,
                           self.username.text];

或者如果你想使用绑定文本。

if (sqlite3_open(dbpath, & contactDB) == SQLITE_OK)
{    
    const char *insert_stmt = "UPDATE profile SET username = ? WHERE id = 1";
    if(sqlite3_prepare_v2(contactDB, insert_stmt,
                          -1, &statement, NULL)== SQLITE_OK)
    {
        sqlite3_bind_text(statement, 1, [self.username.text UTF8String], -1, SQLITE_TRANSIENT);
    }

    if (sqlite3_step(statement) == SQLITE_DONE)
    {
        self.settingStatus.text = @"Contact added";
    } else {
        self.settingStatus.text = @"Failed to add contact";
    }
    sqlite3_finalize(statement);
    sqlite3_close(contactDB);
}   else {
    self.settingStatus.text = @"DB Not Connect";
}

【讨论】:

    【解决方案3】:

    检查一下

       in .h file NSString *databaseName;
                NSString *databasePath;
    
            and in .m file specify  databaseName = @"Db name";
        NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDir = [documentPaths objectAtIndex:0];
        databasePath = [documentsDir stringByAppendingPathComponent:databaseName];
    
                -(void)save:(id)sender
                    {
                        [self checkAndCreateDatabase];
                        sqlite3 *contactDB;
                        sqlite3_stmt *updateStmt;
    
                        if(sqlite3_open([databasePath UTF8String], &contactDB) == SQLITE_OK)
                        {
                            NSString *querySql=[NSString stringWithFormat:
                                               @"UPDATE profile SET username = \"%@\" WHERE id = 1" ,
                                               self.username.text];
                            const char*sql=[querySql UTF8String];
                            if(sqlite3_prepare_v2(contactDB,sql, -1, &updateStmt, NULL) == SQLITE_OK)
                            {
                                if(SQLITE_DONE != sqlite3_step(updateStmt))
                                {
                                    NSLog(@"Error while updating. '%s'", sqlite3_errmsg(contactDB));
                                }
                                else{
                                    sqlite3_reset(updateStmt);
                                    NSLog(@"Update done successfully!");
                                }
                            }
    
                            sqlite3_finalize(updateStmt);
                        }
                        sqlite3_close(contactDB);
                    }
    
    
                    -(void) checkAndCreateDatabase{
    
                        BOOL success;
                        NSFileManager *fileManager = [NSFileManager defaultManager];
                        success = [fileManager fileExistsAtPath:databasePath];
                        if(success) return;
    
                        NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:databaseName];
                        [fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
    
                    }
    

    【讨论】:

    • 显示checkAndCreateDatabase 的代码。停止使用NSAssert1,转而使用NSLog。
    • @jennyProGram 只是检查写入的更新语句是否正确,然后打印 NSLog(@"%@",insertSQL);然后在 db 中运行相同的查询
    • 好的,看起来不错。最后一件事;使用绑定将用户名放入准备好的语句中,而不是 [NSString stringWithFormat:]。
    【解决方案4】:

    有很多可能性请检查以下所有内容:

    1) 用 nil 初始化语句

    sqlite3_stmt    *statement = nil;
    

    2) 在下面试试

    if (sqlite3_prepare_v2(contactDB, insert_stmt,-1, &statement, NULL) == SQLITE_OK)
    {
     while (sqlite3_step(statement) == SQLITE_ROW)
     {
       //Updated
     }
    }
    else
    {
        NSLog(@"error is %s",sqlite3_errmsg(database));
    }
    

    【讨论】:

      【解决方案5】:

      您确定 dbPath 不在应用程序包中吗?我们无法更新包中的 db。

      sqlite3_prepare_v2() and sqlite3_step() will return an int.
      

      你可以在 sqlite3.h 中找到你想要的东西。

      Like #define SQLITE_BUSY         5   /* The database file is locked */ ...
      

      还有,为什么不使用 FMDB?你可以在 Github 上轻松找到它。 (链接https://github.com/ccgus/fmdb)

      【讨论】:

      • 这看起来更像是评论而不是答案。目前无法回答,因为 OP 不知道为什么 UPDATE 会失败,直到他们在代码中引入错误报告。
      • 有一条错误消息:'没有这样的表:配置文件'。实际上我所做的是,在 Firefox 上创建 sqlite,然后我将文件复制并添加到 xcode 项目中。我重新打开了 sqlite 文件,并且有一个“配置文件”表
      • 我认为您需要检查 dbpath。如果你想更新你的 sqlite db,你必须将它从 bundle 复制到本地。
      猜你喜欢
      • 1970-01-01
      • 2021-07-27
      • 2021-04-07
      • 2021-12-19
      • 1970-01-01
      • 2018-11-12
      • 2015-01-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多