2014-04-14 46 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