数据库插入失败

时间:2013-08-21 04:36:47

标签: iphone database json sqlite

我在我的服务器中存储了详细信息。我使用服务器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");
                    }

2 个答案:

答案 0 :(得分:2)

有几个问题:

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

    NSLog(@"InsertFailed");
    

    使用

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

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

  2. SQLite sqlite3_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_reset替换为sqlite3_finalizesqlite3_reset重置语句,以便您可以绑定新值并再次执行它(这不是您需要的)。 sqlite3_finalize释放与准备好的语句关联的内存( 你需要的内容)。

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

     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(我假设从your other question不变)将不符合你在这里的嵌套for循环结构。您的三个阵列是不同类型的阵列。或者您是否因为其他问题而更改了JSON格式?

答案 1 :(得分:-1)

Well check Out here for detailed code structure.

我管理的方式是一个单独的类来管理DB

这些是您寻找的方法

-(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);
    }

}