2014-04-14 78 views
2

我有一個龐大的SQLite文件填滿了查詢來創建我的數據庫表並插入所有記錄。該文件相當大,運行SQL文件似乎比我預期的要長得多。Objective-C - FMDB - 大型SQLite轉儲導入

我正在爲我正在使用的一個iPad應用程序使用FMDB,而且我真的只想用一個新的數據庫替換當前的數據庫文件,但我不確定sql文件是否與數據庫文件相同。它不包含任何相同的標題信息,等等......

什麼是最好的方式去做到這一點?

回答

4

如果做了很多單獨UPDATEINSERT電話與FMDatabase,考慮在年底做beginTransaction開始和commit

[db beginTransaction]; 
// do all of your updates 
[db commit]; 

或者,如果使用FMDatabaseQueue,用inTransaction

[databaseQueue inTransaction:^(FMDatabase *db , BOOL *rollback) { 
    // do all of your updates 
}]; 

如果你沒有使用其中的一個,它會在每次插入之後提交,這使得它慢得多。如果添加大量行(如我在添加/更新大量小記錄時看到兩個數量級的性能差異),則差異可能會很大。


上面假定您正在嘗試執行一系列單獨的SQL命令。如果它全部在一個文件中(例如.dump輸出),FMDB在歷史上還沒有一個接口來做到這一點(即使有SQLite功能,sqlite3_exec,就是這樣做)。 extra文件夾最近增加了一個名爲FMDatabaseSplitter的文件夾,該文件夾試圖將​​一長串SQL分割成單獨的調用,然後您可以單獨調用它們。

個人而言,它使我很緊張地使用第三方SQL解析例程,所以我只是傾向於直接調用SQLite函數sqlite3_exec。要做到這一點,你可以使用FMDB sqliteHandle方法從FMDatabase對象訪問sqlite3指針,然後使用結合sqlite3_exec功能直接:

NSError *error = nil; 
NSString *dumpSQL = [NSString stringWithContentsOfFile:dumpFilePath encoding:NSUTF8StringEncoding error:&error]; 
NSAssert(dumpSQL, @"Loading of SQL failed: %@", error); 

int rc = sqlite3_exec(db.sqliteHandle, [dumpSQL UTF8String], NULL, NULL, NULL); 
if (rc != SQLITE_OK) { 
    NSLog(@"sqlite3_exec error: %@", [db lastErrorMessage]); 
} 

我必須承認,這讓我有點緊張只需將批量SQL導入到應用程序的數據庫中即可。如果您沒有特別小心,SQL中一個無辜的錯誤可能會阻止您的整個安裝基礎的應用程序。我寧願從服務器上看到應用程序請求JSON或XML提要,然後自己進行更新,但是如果您想使用輸出來更新應用程序的FMDB數據庫,那麼這是一種方法。


FMDB V2.3已經推出了一個名爲executeStatementssqlite3_exec的包裝:

BOOL success; 

NSString *sql = @"create table bulktest1 (id integer primary key autoincrement, x text);" 
       "create table bulktest2 (id integer primary key autoincrement, y text);" 
       "create table bulktest3 (id integer primary key autoincrement, z text);" 
       "insert into bulktest1 (x) values ('XXX');" 
       "insert into bulktest2 (y) values ('YYY');" 
       "insert into bulktest3 (z) values ('ZZZ');"; 

success = [db executeStatements:sql]; 
+0

這是一些非常好的建議......但是我怎麼會做這樣一個大的SQL文件? – rckehoe

+0

我確實使用JSON最初請求所有數據,問題在於它需要很長時間才能打開。所以我不得不想一個不同的方式。 – rckehoe

+1

@rckehoe夠公平的。如果SQL文件小得多,我會感到驚訝。我不知道在傳輸時間內有多少性能問題是真的,有多少問題是沒有事務(如果通過SQL執行'BEGIN TRANSACTION'和'COMMIT',如果使用了'beginTransaction'和'commit' FMDB接口)。看到在更新過程中通過使用事務可以實現多少性能改進,這確實令人驚訝。我是一個實用主義者,所以如果使用SQL文件有幫助,那很好,但如果真的是這個問題,我會感到驚訝。 – Rob