我有一个很大的SQLite文件,其中充满了查询以创建数据库表并插入所有记录。该文件相当大,运行SQL文件似乎比我预期的要花费更长的时间。
我正在为正在处理的iPad应用程序使用FMDB,我确实只想用一个新的数据库文件替换当前的数据库文件,但是我不确定sql文件是否与数据库文件相同。它不包含任何相同的标头信息,等等。
这样做的最佳方法是什么?
最佳答案
如果使用UPDATE
分别进行许多INSERT
或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 sqlite3
方法从FMDatabase
对象访问sqliteHandle
指针,然后将其与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提要,然后自己进行更新,但是如果您想使用
.dump
输出来使用FMDB更新应用程序的数据库,这是一种实现方法。FMDB v2.3为
sqlite3_exec
引入了一个名为executeStatements
的包装器: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];
关于objective-c - Objective-C-FMDB-大型SQLite转储导入,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23065693/