2013-08-21 102 views
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"); 
        } 

回答

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_resetsqlite3_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格式?

+0

在改變基於1的索引後,我插入了日誌。但數據沒有插入到db1.sqlite表中。我通過SQLiteManager打開了db1.sqlite文件。但表格沒有任何值。爲什麼? – user2674668

+0

@ user2674668你在模擬器上運行這個嗎?你是否在模擬器的Document文件夾中打開數據庫(而不是在項目文件夾或應用程序包中的副本)?它位於〜/ Library/Application Support/iPhone Simulator/....如果在Mac OS中無法看到您的Library文件夾,則可能必須執行'chflags nohidden〜/ Library'。 – Rob

+0

我在下面得到NSLog:綁定1失敗:綁定或列索引超出範圍,綁定2失敗:綁定或列索引超出範圍,綁定3失敗:綁定或列索引超出範圍 – user2674668

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

} 
+0

你能檢查我的代碼嗎?並告訴我在哪裏我把錯誤 – user2674668