2013-06-04 57 views
2

我的應用程序從fmdatabase中讀取一些數據並使用核心圖庫以圖形方式顯示它。在我的應用程序第一次讀取數據庫時,所有這一切都很好,但問題是在將新數據插入數據庫之後,我執行了一個sql select語句,並且它不讀取插入的新行。我不知道可能是什麼問題,因爲在sqlite studio中,我在執行插入操作並獲取數據後執行相同的select語句。我如何從FMDatabase中讀取新插入的數據

我已經閱讀了有關我必須將資源數據庫複製到另一個文件夾,以便我可以讀/寫它,但也不工作。

你有什麼想法嗎?

我的開頭代碼是這樣的。

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,   NSUserDomainMask, YES); 
NSString *docsPath = [paths objectAtIndex:0]; 
NSString *writablePath = [docsPath stringByAppendingPathComponent:@"DatabaseName.sqlite"]; 
//this is the copy db from the resource database 
FMDatabase *db = [FMDatabase databaseWithPath:writablePath]; 

這裏是插入和刪除的代碼。

if([db open]){ 
    for (int i = 0; i < [updatedData count]; i++) { 
     z_ent = [((NSNumber *)([[updatedData objectAtIndex:i] valueForKey:@"ent"])) intValue]; 
     z_opt = [((NSNumber *)[[updatedData objectAtIndex:i] valueForKey:@"opt"]) intValue]; 
     zaniocorte = [((NSNumber *)[[updatedData objectAtIndex:i] valueForKey:@"anioCorte"]) intValue]; 
     zmescorte = [((NSNumber *)[[updatedData objectAtIndex:i] valueForKey:@"mesCorte"]) intValue]; 
     zestatus = [((NSNumber *)[[updatedData objectAtIndex:i] valueForKey:@"estatus"]) intValue]; 
     zidcontraparte = [((NSNumber *)[[updatedData objectAtIndex:i] valueForKey:@"idContraparte"]) intValue]; 

     zconsumomesa = [((NSNumber *)[[updatedData objectAtIndex:i] valueForKey:@"consumo"]) doubleValue]; 
     zconsumototal = [((NSNumber *)[[updatedData objectAtIndex:i] valueForKey:@"consumoTotal"]) doubleValue]; 
     zlinea = [((NSNumber *)[[updatedData objectAtIndex:i] valueForKey:@"linea"]) doubleValue]; 
     zlineadisponible = [((NSNumber *)[[updatedData objectAtIndex:i] valueForKey:@"lineaDisponible"]) doubleValue]; 

     zcontraparte = ((NSString *)[[updatedData objectAtIndex:i] valueForKey:@"contraparte"]); 
     zinstitucion = ((NSString *)[[updatedData objectAtIndex:i] valueForKey:@"institucion"]); 
     zmesa = ((NSString *)[[updatedData objectAtIndex:i] valueForKey:@"mesa"]); 
     ztiporiesgo = ((NSString *)[[updatedData objectAtIndex:i] valueForKey:@"tipoRiesgo"]); 

     queryUpdateInsert = [NSString stringWithFormat:@"INSERT INTO ZTESORERIACONSOLIDADO 
(Z_ENT, Z_OPT, ZANIOCORTE, ZMESCORTE, ZCONSUMOMESA, ZCONSUMOTOTAL, ZESTATUS, ZLINEA, ZLINEADISPONIBLE, ZCONTRAPARTE, ZIDCONTRAPARTE, ZINSTITUCION, ZMESA, ZTIPORIESGO) VALUES (%d, %d, %d, %d, %f, %f, %f, %f, %f, '%@', %d, '%@', '%@', '%@');",z_ent, z_opt, zaniocorte, zmescorte, zconsumomesa, zconsumototal, zestatus, zlinea, zlineadisponible, zcontraparte, zidcontraparte, zinstitucion, zmesa, ztiporiesgo]; 

     queryUpdateDelete = [NSString stringWithFormat:@"DELETE FROM ZTESORERIACONSOLIDADO WHERE ZMESCORTE = %d AND ZANIOCORTE = %d", zmescorte, zaniocorte-1]; 

     del = [db executeUpdate:queryUpdateDelete]; 
     ins = [db executeUpdate:queryUpdateInsert]; 
    } 
} 
[db close]; 
+2

您是否在插入後關閉了光標? – HalR

回答

0

根據您現在提供的代碼進行一些觀察。

  1. 檢查返回值。

    你應該從executeUpdate檢查delins返回值,如果任是NO,你應該檢查lastErrorMessage

    del = [db executeUpdate:queryUpdateDelete]; 
    if (!del) 
        NSLog(@"%s: executeUpdate delete error: %@", __FUNCTION__, [db lastErrorMessage]); 
    
    ins = [db executeUpdate:queryUpdateInsert]; 
    if (!ins) 
        NSLog(@"%s: executeUpdate insert error: %@", __FUNCTION__, [db lastErrorMessage]); 
    
  2. 不要使用stringWithFormat

    你真的不應該使用stringWithFormat構建SQL,而是用在SQL的?佔位符,然後傳遞參數executeUpdate

    queryUpdateInsert = @"INSERT INTO ZTESORERIACONSOLIDADO (Z_ENT, Z_OPT, ZANIOCORTE, ZMESCORTE, ZCONSUMOMESA, ZCONSUMOTOTAL, ZESTATUS, ZLINEA, ZLINEADISPONIBLE, ZCONTRAPARTE, ZIDCONTRAPARTE, ZINSTITUCION, ZMESA, ZTIPORIESGO) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"; 
    
    queryUpdateDelete = @"DELETE FROM ZTESORERIACONSOLIDADO WHERE ZMESCORTE = ? AND ZANIOCORTE = ?"; 
    
    del = [db executeUpdate:queryUpdateDelete, @(zmescorte), @(zaniocorte-1)]; 
    if (!del) 
        NSLog(@"%s: executeUpdate delete error: %@", __FUNCTION__, [db lastErrorMessage]); 
    
    ins = [db executeUpdate:queryUpdateInsert, @(z_ent), @(z_opt), @(zaniocorte), @(zmescorte), @(zconsumomesa), @(zconsumototal), @(zestatus), @(zlinea), @(zlineadisponible), zcontraparte, @(zidcontraparte), zinstitucion, zmesa, ztiporiesgo]; 
    if (!ins) 
        NSLog(@"%s: executeUpdate insert error: %@", __FUNCTION__, [db lastErrorMessage]); 
    

    請注意與更換printf風格格式化? SQL佔位符。

    另請注意,executeUpdate需要NSNumber對象而不是原始數字數據類型。所以,在我上面的例子中,你存儲NSNumberdouble變量的值,我不得不使用@()來獲得NSNumber表示。更好的是,不要從convertedData中檢索NSNumber,將其轉換爲基本數據類型,如NSIntegerdouble,然後轉換回NSNumber,只需傳遞從valueForKey返回的原始對象並丟失@()。如果你這樣做,顯然你必須改變變量的數據類型,但這是一種更合乎邏輯的方法。)

    但是,關鍵的回收信息是,你想避免需要轉義任何特殊字符通過使用executeUpdate而不是stringWithFormat的參數來保護自己免受SQL注入攻擊。 (使用executeUpdate中的附加參數就像在SQLite庫中使用sqlite3_bind_xxx調用本身。)

  3. 這是CoreData數據庫嗎?

    我是否從表名和列名中的Z推斷出這是一個CoreData數據庫?如果是這樣,除非你完全退役CoreData,否則我不會建議通過SQLite直接與數據庫交互(無論是通過FMDB還是通過調用sqlite3_xxx)。當然,如果您在嘗試使用FMDB代碼時打開CoreData,則可能會出現問題(當您查看lastErrorMessage時,會發出問題)。

  4. 但是,如果使用SQLite,則使用事務。

    如果要細化算法(一旦你確認並修復你的bug的來源),你可能想換這一切的一個inTransaction調用內部,因爲如果你有很多的記錄,這樣做,你可以獲得顯着的性能提升。

相關問題