【问题标题】:saving json data into sqlite database in iOS在 iOS 中将 json 数据保存到 sqlite 数据库中
【发布时间】:2016-09-13 20:16:13
【问题描述】:

我的问题是如何将获取的 JSON 数组数据插入 sqlite 数据库。 我已经获取了 JSON 数据,它是一个字典数组。

我保存 JSON 结果的代码如下所示:

-(BOOL) saveApiResults: (NSString *)tableName : (NSArray *)data
{
    BOOL saveSuccess = NO;

    @try {
        const char *dbPath = [databasePath UTF8String];
        if(sqlite3_open(dbPath,&database)==SQLITE_OK) {

            sqlite3_exec(database, "BEGIN", 0, 0, 0);

            //pass an array containing json dictionary to below line
            NSDictionary *rowData=[data objectAtIndex:0];
            NSArray *keyArray = [rowData allKeys];
            NSLog(@"key array %@",keyArray);
            NSString *insertSQL=@"INSERT INTO ";
            insertSQL=[insertSQL stringByAppendingString:@"moodsdata"];
            insertSQL=[insertSQL stringByAppendingString:@" VALUES("];
            for(int j=0;j<[keyArray count];j++)
            {
                insertSQL=[insertSQL stringByAppendingString:@"?"];
                if(j<[keyArray count]-1)
                    insertSQL=[insertSQL stringByAppendingString:@","];
            }
            insertSQL=[insertSQL stringByAppendingString:@");"];


            NSLog(@"query : %@ ",insertSQL);

            const char *sqlstatement = [insertSQL UTF8String];

            sqlite3_stmt *compiledstatement;

            if(sqlite3_prepare_v2(database,sqlstatement , -1, &compiledstatement, NULL)==SQLITE_OK) {

                for (NSUInteger i = 0; i < [data count]; i++) {
                    NSDictionary *rowData=[data objectAtIndex:0];
                    for(int j=0;j<[keyArray count];j++) {
                        NSString *val = @"";
                        NSString *value=(NSString *)[rowData objectForKey:[keyArray objectAtIndex:j]];
                        if((value != nil) && (![value isEqual:[NSNull null]]))
                            val=[NSString stringWithFormat:@"%@",value];
                        NSLog(@"values  %@",val);
                        sqlite3_bind_text(compiledstatement,j+1,[val UTF8String], -1, SQLITE_TRANSIENT);
                    }

                    if(sqlite3_step(compiledstatement) != SQLITE_DONE) {
                        NSLog(@"ERROR");
                    }

                    sqlite3_clear_bindings(compiledstatement);
                    sqlite3_reset(compiledstatement);


                }

                sqlite3_exec(database, "COMMIT", 0, 0, 0);
                saveSuccess = YES;
                NSLog(@"RESULTS SAVED SUCCESSFULLY!");


            } else {
                NSLog(@"StatemenT FAILED (%s)", sqlite3_errmsg(database));
            }

            sqlite3_finalize(compiledstatement);

        } else {
            NSLog(@"Statement FAILED (%s)", sqlite3_errmsg(database));
        }
    }
    @catch (NSException *exception) {
        NSLog(@"NSException : %@",exception.description);
    }
    @finally {
        sqlite3_close(database);
    }

    return saveSuccess;
}

我的问题是,当我尝试将 JSON 数组传递给此方法时,它只会保存第一个数组对象的值。即只保存第一个字典值。请告诉我我做错了什么。

【问题讨论】:

  • 请使用与您的问题相关的代码更新您的问题。你都尝试了些什么?您问题中的代码与您的问题无关。
  • 不相关,但你为什么要这样构建CREATE 语句?为什么它不是单个字符串文字?至少使用NSMutableString 一块一块地构建它。
  • 我已经更新了我的问题。请检查一下。

标签: ios arrays json sqlite relational-database


【解决方案1】:

在您获取值的代码中,您正在获取行数据:

NSDictionary *rowData=[data objectAtIndex:0];

我怀疑你的意思是:

NSDictionary *rowData=[data objectAtIndex:i];

【讨论】:

  • 现在我想在表格中再添加一列。在我的项目中,我有一个表格视图,其中显示了从 sqlite 数据库中获取的所有数据。但现在我想保存 tableView 单元格的值。例如,如果我选择第一个单元格,那么它应该将其保存在数据库的新列中并说“选择并保存的心情 1”,如果我选择第三个单元格,它应该将其保存在数据库的新列中并说“选择并保存的心情 3”,等等......谁能帮我解决这个问题@Rob
  • 我不太了解您的要求。我建议您在 Stack Overflow 上发布新问题,向我们展示您尝试了什么,尝试时发生了什么,并描述您想要发生的事情。但是您上面的评论不足以让我诊断出发生了什么。
【解决方案2】:

您的主要问题是您在执行实际插入的循环中错误地访问了data[0] 而不是data[i]

但是这段代码还有很多其他的小问题。这是您的所有代码:

-(BOOL) saveApiResults:(NSString *)tableName data:(NSArray *)data
{
    BOOL saveSuccess = NO;

    const char *dbPath = [databasePath UTF8String];
    if (sqlite3_open(dbPath,&database) == SQLITE_OK) {
        sqlite3_exec(database, "BEGIN", 0, 0, 0);

        //pass an array containing json dictionary to below line
        NSDictionary *rowData = data[0];
        NSArray *keyArray = [rowData allKeys];
        NSLog(@"key array %@",keyArray);

        NSMutableString *insertSQL = @"INSERT INTO moods data VALUES(";
        for (NSInteger j = 0; j < [keyArray count]; j++)
        {
            if (j) {
                [insertSQL appendString:@","];
            }
            [insertSQL appendString:@"?"];
        }
        [insertSQL appendString:@");"];
        NSLog(@"query : %@ ",insertSQL);

        const char *sqlstatement = [insertSQL UTF8String];
        sqlite3_stmt *compiledstatement;

        if (sqlite3_prepare_v2(database, sqlstatement, -1, &compiledstatement, NULL) == SQLITE_OK) {
            for (NSDictionary *rowData in data) {
                for (NSInteger j = 0; j < [keyArray count]; j++) {
                    NSString *val = @"";
                    NSString *value = rowData[keyArray[j];
                    if (value && ![value isEqual:[NSNull null]]) {
                        val = [NSString stringWithFormat:@"%@",value];
                    }
                    NSLog(@"values %@",val);
                    sqlite3_bind_text(compiled statement, j + 1, [val UTF8String], -1, SQLITE_TRANSIENT);
                }

                if (sqlite3_step(compiledstatement) != SQLITE_DONE) {
                    NSLog(@"ERROR");
                }

                sqlite3_reset(compiledstatement);
            }

            sqlite3_exec(database, "COMMIT", 0, 0, 0);
            sqlite3_finalize(compiledstatement);
            saveSuccess = YES;
            NSLog(@"RESULTS SAVED SUCCESSFULLY!");
        } else {
            NSLog(@"StatemenTtFAILED (%s)", sqlite3_errmsg(database));
        }

        sqlite3_close(database);
    } else {
        NSLog(@"Statement FAILED (%s)", sqlite3_errmsg(database));
    }

    return saveSuccess;
}
  1. 不需要try/catch。只需进行适当的错误检查即可。
  2. 使用NSMutableString 逐段构建字符串。
  3. 只有在成功准备好声明后才能完成。
  4. 如果打开数据库,请务必关闭它。
  5. 使用现代语法访问字典和数组中的值。它更易于阅读和输入。
  6. 尽可能使用现代循环。
  7. 使用空格。它使代码更易于阅读。
  8. 为所有方法参数命名。

但是您的 SQLite 代码实际上比这里的大多数帖子要好。您实际上使用sqlite_bind_xxx 将值绑定到您的查询。这样做的人太少了。

【讨论】:

    猜你喜欢
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-16
    • 2018-04-27
    • 2020-03-22
    相关资源
    最近更新 更多