iOS - SQLite插入不插入数据

时间:2014-02-02 05:12:03

标签: ios sqlite

- (id)init {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *databasePath = [documentsDirectory stringByAppendingPathComponent:@"idataBase.sqlite3"];
    NSLog(@"Doc path: %@",databasePath);
    bool databaseAlreadyExists = [[NSFileManager defaultManager] fileExistsAtPath:databasePath];
    if (!databaseAlreadyExists){
        NSString *databasePathFromApp = [[NSBundle mainBundle] pathForResource:@"idataBase" ofType:@"sqlite3"];
        NSLog(@"Main bundle path: %@",databasePathFromApp);
        [[NSFileManager defaultManager] copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
    }
    if (sqlite3_open([databasePath UTF8String], &_database) == SQLITE_OK){
        NSLog(@"Database opened");
    }dd
    return self;
}

-(void) setData:(NSDictionary *)data{
    NSLog(@"In Data %@",data);
    NSString *hostAddress = [data objectForKey:@"hostAddress"];
    NSString *userName = [data objectForKey:@"userName"];
    NSString *passKey = [data objectForKey:@"passKey"];
    NSString *listName = [data objectForKey:@"listName"];
    NSString *q = [NSString stringWithFormat:@"INSERT INTO user_info (host_name,user_name,password,text_name) VALUES (\"%@\", \"%@\", \"%@\", \"%@\")",hostAddress,userName,passKey,listName];
    NSLog(@"%@",q);
    sqlite3_stmt    *statement = NULL;
    const char *insertQuery = [q UTF8String];
    sqlite3_prepare_v2(_database, insertQuery, -1, &statement, NULL);
    if(sqlite3_step(statement) == SQLITE_OK){
        NSLog(@"Data Inserted");
    }
    sqlite3_finalize(statement);
    sqlite3_close(_database);

}

我使用上面的代码插入数据。数据库连接在init方法中打开。但是我无法在数据库中插入数据。 sqlite3_step(statement)永远不会返回SQLITE_OK。

1 个答案:

答案 0 :(得分:3)

你说:

  

sqlite3_step(statement)永远不会返回SQLITE_OK。

正确,如果成功,则返回SQLITE_DONE(执行插入/更新/删除查询时)。请参阅sqlite3_step documentation

如果您没有SQLITE_DONE,那么您应该检查sqlite3_errmsg以确定原因。如果它的报告“的呼叫顺序库程序”的错误,这可能意味着sqlite3_prepare_v2失败,它实际上是说,它的看到sqlite3_step没有成功sqlite3_prepare_v2呼叫。

所以,你也应该检查的结果,sqlite3_prepare_v2(因为这是更频繁,问题的来源),并确保为SQLITE_OK,如果没有,看看{{在调用sqlite3_errmsg之前立即1}}。如果您从sqlite3_step收到错误并忽略该错误并只调用sqlite3_prepare_v2,则在调用sqlite3_step之前,您将丢失可能已检查过的有意义的错误消息,从而替换有意义的错误消息使用“库程序不按顺序”错误。


这纯粹是主观臆测,但在复制数据库中给出的有关问题与其他问题,我可以打赌,在您的测试一段时间,你跑你的代码的演绎未能复制数据库,但仍继续打电话sqlite3_stepsqlite3_open如果找不到空数据库,则会创建一个空数据库。因此,如果数据库为空,我不会感到惊讶,因此来自sqlite3_open的错误消息将报告找不到该表。如果我的猜想是正确的(即sqlite3_prepare_v2是失败的,并呼吁sqlite3_prepare_v2报道称,该表中没有找到),我建议从你的模拟器/设备移除应用程式(以消除任何空白数据库坐在sqlite3_errmsg文件夹中)并尝试再次运行该应用程序。如果捆绑包中的副本失败,我还要确保您的代码不会尝试打开数据库(否​​则您将面临再次创建空白数据库的风险)。我可能还建议您将Documents代码替换为:

sqlite3_open

这与if (sqlite3_open_v2([databasePath UTF8String], &_database, SQLITE_OPEN_READWRITE, NULL) == SQLITE_OK) NSLog(@"Database opened"); 类似,但如果找不到空数据库,则不会创建空白数据库。


因此,检查所有SQLite返回码并在SQL中使用sqlite3_open占位符的例程可能如下所示:

?

将字符串值绑定到列的方法可能如下所示:

- (void)insertUserInfo:(NSDictionary *)dictionary
{
    NSString *hostAddress = dictionary[@"hostAddress"];
    NSString *userName    = dictionary[@"userName"];
    NSString *passKey     = dictionary[@"passKey"];
    NSString *listName    = dictionary[@"listName"];

    const char *sql = "INSERT INTO user_info (host_name,user_name,password,text_name) VALUES (?, ?, ?, ?)";

    sqlite3_stmt *statement = NULL;

    if (sqlite3_prepare_v2(_database, sql, -1, &statement, NULL) != SQLITE_OK) {
        NSLog(@"prepare failed: %s", sqlite3_errmsg(_database));
        return;
    }

    if (![self bindString:hostAddress column:1 statement:statement])
        return;

    if (![self bindString:userName column:2 statement:statement])
        return;

    if (![self bindString:passKey column:3 statement:statement])
        return;

    if (![self bindString:listName column:4 statement:statement])
        return;

    if (sqlite3_step(statement) == SQLITE_DONE) {
        NSLog(@"Data Inserted");
    } else {
        NSLog(@"Insert failed: %s", sqlite3_errmsg(_database));
    }
    sqlite3_finalize(statement);
}