0

我将详细信息存储在我的服务器中。我使用服务器 url 获取详细信息并存储到数据库表。我插入失败的 NSLog。我在文档文件夹中有 2 个 sqlite 文件。在 copyItemAtPath 之后,我正在写入该文件。

代码:

NSFileManager *fileMgr = [NSFileManager defaultManager];
     NSError *err;

     NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"db5" ofType:@"sqlite"];
     //NSLog(@"bundlePath %@", bundlePath);


     //call update function to check any data updated,
     //if there is a version difference
     //update the data base with all the required fileds.



     NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
     NSString *documentsDirectory = [paths objectAtIndex:0];
     //NSLog(@"docs dir is %@", documentsDirectory);

     NSString *appFile = [documentsDirectory stringByAppendingPathComponent:@"db1.sqlite"];

     //  [fileMgr copyItemAtPath:bundlePath toPath:appFile error:&err];

     BOOL success = [fileMgr copyItemAtPath:bundlePath toPath:appFile error:&err];


     if (!success) {
     NSLog(@"Failed to create writable database file with message '%@'.", [err localizedDescription]);
     }



    NSURL *URL = [NSURL URLWithString:@"http://myserver.net/projects/mobile/jsonstring.php"];



    NSError *error;
    NSString *stringFromFileAtURL = [[NSString alloc]
                                     initWithContentsOfURL:URL
                                     encoding:NSUTF8StringEncoding
                                     error:&error];

    //NSLog(@"response is %@", stringFromFileAtURL);

      NSString *path = [documentsDirectory stringByAppendingPathComponent:@"db1.sqlite"];
    //NSLog(@"filepath %@",path);



    //array

    NSArray *userData = [stringFromFileAtURL JSONValue];
    [stringFromFileAtURL release];


   // NSLog(@"userdata is %@", userData);

    int  i = 0;
     BOOL notExist = TRUE;
 //   sqlite3_stmt *statement, *addStmt;


    for (NSArray *skarray in userData) {
        //NSLog(@"test");


        if(i == 0){
            //insert all main category
            for (NSDictionary *tuser in skarray) {


NSString *query = @"delete from categories";
                    const char *sqlStatement = [query UTF8String];
                    sqlite3_stmt *compiledStatement;
                    if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {
                        // Loop through the results and add them to the feeds array
                        while(sqlite3_step(compiledStatement) == SQLITE_ROW) {
                            // Read the data from the result row
                            NSLog(@"result is here");
                        }

                        // Release the compiled statement from memory
                        sqlite3_finalize(compiledStatement);


                    }

               if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) {


                    NSLog(@"path is %s", [path UTF8String]);


                    sqlite3_stmt *addStmt = NULL;
                    const char *sqlInsert = "INSERT INTO categories (id,cat_name,order_by) VALUES(?, ?, ?)";

                    int result = sqlite3_prepare_v2(database,sqlInsert, -1, &addStmt, NULL);
                    if(result != SQLITE_OK){
                        NSAssert1(0, @"Error while creating add statement. '%s'", sqlite3_errmsg(database));
                    }

                    sqlite3_bind_text(addStmt, 0, [[tuser objectForKey:@"id"] UTF8String], -1, SQLITE_TRANSIENT);
                    sqlite3_bind_text(addStmt, 1, [[tuser objectForKey:@"cat_name"] UTF8String], -1, SQLITE_TRANSIENT);
                    sqlite3_bind_text(addStmt, 2, [[tuser objectForKey:@"order_by"] UTF8String], -1, SQLITE_TRANSIENT);

                    //Execute the statement
                    if (result == SQLITE_OK) {
                        result = sqlite3_step(addStmt);
                    }

                    if (result == SQLITE_DONE || result == SQLITE_ROW) {
                        result = sqlite3_reset(addStmt);
                        NSLog(@"Inserted");
                    }
                    else{
                        NSLog(@"InsertFailed");
                    }
4

2 回答 2

2

几个问题:

  1. 如果您想知道插入失败的原因,请替换

    NSLog(@"InsertFailed");
    

    NSLog(@"Insert failed: %s", sqlite3_errmsg(database));
    

    每当您遇到 SQL 错误时,请检查错误是什么,否则您会失明。

  2. SQLitesqlite3_bind_xxx函数使用从 1 开始的索引(与sqlite3_column_xxx函数不同)。所以替换:

    sqlite3_bind_text(addStmt, 0, [[tuser objectForKey:@"id"] UTF8String], -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(addStmt, 1, [[tuser objectForKey:@"cat_name"] UTF8String], -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(addStmt, 2, [[tuser objectForKey:@"order_by"] UTF8String], -1, SQLITE_TRANSIENT);
    

    和:

    sqlite3_bind_text(addStmt, 1, [[tuser objectForKey:@"id"] UTF8String], -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(addStmt, 2, [[tuser objectForKey:@"cat_name"] UTF8String], -1, SQLITE_TRANSIENT);
    sqlite3_bind_text(addStmt, 3, [[tuser objectForKey:@"order_by"] UTF8String], -1, SQLITE_TRANSIENT);
    

    或者,甚至更好:

    if (sqlite3_bind_text(addStmt, 1, [[tuser objectForKey:@"id"] UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK)
        NSLog(@"bind of 1 failed: %s", sqlite3_errmsg(database));
    if (sqlite3_bind_text(addStmt, 2, [[tuser objectForKey:@"cat_name"] UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK)
        NSLog(@"bind of 2 failed: %s", sqlite3_errmsg(database));
    if (sqlite3_bind_text(addStmt, 3, [[tuser objectForKey:@"order_by"] UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK)
        NSLog(@"bind of 3 failed: %s", sqlite3_errmsg(database));
    

    或者,甚至更好:

    if ([[tuser objectForKey:@"id"] isKindOfClass:[NSString class]])
    {
        if (sqlite3_bind_text(addStmt, 1, [[tuser objectForKey:@"id"] UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK)
            NSLog(@"bind of 1 failed: %s", sqlite3_errmsg(database));
    }
    else
    {
        if (sqlite3_bind_null(addStmt, 1) != SQLITE_OK)
            NSLog(@"bind of null to 1 failed: %s", sqlite3_errmsg(database));
    }
    
    if ([[tuser objectForKey:@"cat_name"] isKindOfClass:[NSString class]])
    {
        if (sqlite3_bind_text(addStmt, 2, [[tuser objectForKey:@"cat_name"] UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK)
            NSLog(@"bind of 2 failed: %s", sqlite3_errmsg(database));
    }
    else
    {
        if (sqlite3_bind_null(addStmt, 2) != SQLITE_OK)
            NSLog(@"bind of null to 2 failed: %s", sqlite3_errmsg(database));
    }
    
    if ([[tuser objectForKey:@"order_by"] isKindOfClass:[NSString class]])
    {
        if (sqlite3_bind_text(addStmt, 3, [[tuser objectForKey:@"order_by"] UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK)
            NSLog(@"bind of 3 failed: %s", sqlite3_errmsg(database));
    }
    else
    {
        if (sqlite3_bind_null(addStmt, 3) != SQLITE_OK)
            NSLog(@"bind of null to 3 failed: %s", sqlite3_errmsg(database));
    }
    
  3. 将您的替换sqlite3_resetsqlite3_finalize. sqlite3_reset重置语句,以便您可以绑定新值并再次执行它(这不是您需要的)。sqlite3_finalize释放与准备好的语句相关的内存(这您需要的)。

  4. 顺便说一句,无论数据库是否已经存在,您的代码都会将文件从包中复制到 Documents(这意味着您将在下次运行应用程序时丢弃您插入的任何内容)。您可能想要替换:

     BOOL success = [fileMgr copyItemAtPath:bundlePath toPath:appFile error:&err];
    
     if (!success) {
         NSLog(@"Failed to create writable database file with message '%@'.", [err localizedDescription]);
     }
    

    if (![fileMgr fileExistsAtPath:appFile]) {
        BOOL success = [fileMgr copyItemAtPath:bundlePath toPath:appFile error:&err];
    
        if (!success) {
            NSLog(@"Failed to create writable database file with message '%@'.", [err localizedDescription]);
        }
    }
    
  5. 以上所有内容都修复了代码示例中的简单逻辑错误。您仍然有更深层次的问题,即您的 JSON(我假设它与您的其他问题没有变化)将不符合for您在此处获得的嵌套循环结构。您的三个数组是不同类型的数组。或者自从其他问题以来,您是否更改了 JSON 格式?

于 2013-08-21T07:00:26.613 回答
-1

好吧,在这里查看详细的代码结构。

我管理的方式是一个单独的类来管理数据库

这些是您寻找的方法

-(void) checkAndCreateDatabase
{
    // Check if the SQL database has already been saved to the users phone, if not then copy it over
    BOOL success;

    // Create a FileManager object, we will use this to check the status
    // of the database and to copy it over if required
    NSFileManager *fileManager = [NSFileManager defaultManager];

    // Check if the database has already been created in the users filesystem
    success = [fileManager fileExistsAtPath:_databasePath];

    // If the database already exists then return without doing anything
    if(success) return;

    // If not then proceed to copy the database from the application to the users filesystem

    // Get the path to the database in the application package
    NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:_databaseName];

    // Copy the database from the package to the users filesystem
    [fileManager copyItemAtPath:databasePathFromApp toPath:_databasePath error:nil];

}

//-----------------------------------------------------------------------------------------------------//
#pragma mark - Helper methods
//-----------------------------------------------------------------------------------------------------//

-(BOOL)dbOpenedSuccessfully
{
    if(sqlite3_open([[self dbPath] UTF8String], &_database) == SQLITE_OK)
    {
        return YES;
    }
    else
    {
        [[[UIAlertView alloc]initWithTitle:@"Error"
                                   message:@"Error on opening the DB"
                                  delegate:self
                         cancelButtonTitle:@"OK"
                         otherButtonTitles:nil, nil]show];
        return NO;
    }
}






//-----------------------------------------------------------------------------------------------------//
#pragma mark - Query
//-----------------------------------------------------------------------------------------------------//


- (void) executeQuery:(NSString *)strQuery
{
    char *error = NULL;
    if([self dbOpenedSuccessfully])
    {
        NSLog(@"%@",strQuery);
        sqlite3_exec(_database, [strQuery UTF8String], NULL, NULL,&error);
        if (error!=nil) {
            NSLog(@"%s",error);
        }
        sqlite3_close(_database);
    }

}
于 2013-08-21T04:51:09.353 回答