如何在 iOS 中覆盖 SQLite 数据库

Posted

技术标签:

【中文标题】如何在 iOS 中覆盖 SQLite 数据库【英文标题】:How to overwrite a SQLite DB in iOS 【发布时间】:2013-04-29 17:12:52 【问题描述】:

我在使用 SQLlite 数据库的地方创建了一个应用程序...如果需要,我会在应用程序第一次启动时使用以下方法将该数据库复制到 NSCaches 目录中:

- (void) copyDatabaseIfNeeded 

//Using NSFileManager we can perform many file system operations.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSString *dbPath = [self getDBPath];
BOOL success = [fileManager fileExistsAtPath:dbPath];

if(!success) 


    NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"datenbankSpeed"];
    success = [fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error];

    if (!success)
        NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);



- (NSString *) getDBPath 

//Search for standard documents using NSSearchPathForDirectoriesInDomains
//First Param = Searching the documents directory
//Second Param = Searching the Users directory and not the System
//Expand any tildes and identify home directories.


NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory , NSUserDomainMask, YES);
NSString *documentsDir = [paths lastObject];
return [documentsDir stringByAppendingPathComponent:@"datenbankSpeed"];

我的问题是,如果我更改 Database- 文件并为我的客户创建一个新的应用程序文件,他们会在旧应用程序上安装新应用程序,但旧数据库仍在使用中,这将导致崩溃!

【问题讨论】:

【参考方案1】:

我假设问题仅出在您更改数据库架构时。在 sqlite 数据库中创建一个版本表并添加一个列 schema_version 并使用代码中的值填充它。现在,每当您更改 sql 架构时,请更新代码中的 schema_version 编号。在copyDatabaseIfNeeded 中,检查您是否有现有的db 文件,打开它并阅读schema_version。如果此版本与您当前的版本相同,那么您很好。否则,您需要迁移架构。您可能还希望将数据迁移到新架构中。

编辑:为了澄清 - 在copyDatabaseIfNeeded,请执行以下操作:

int version = ... // read schema_version from db
if (version != kCurrentSchemaVersion)

    // convert the schema into new version preserving data if required. 
    // this can be a multi-step process. Eg. if user directly upgrades to schema_version 3
    // after schema_version 1, first you'll convert from 1->2, then 2->3. 

您可能还想看看@Martin 在 cmets 中提到的PRAGMA user_version

【讨论】:

我认为你可以使用 PRAGMA user_version 来达到这个目的。 感谢您的信息。您应该添加一个解释如何使用它的答案。 是的,这听起来不错,但是如何在我的 copyDatabaseIfNeeded 中准确地做到这一点?!你能举个例子吗?! 但是我可以用没有新列的数据库做什么?!有没有办法强制应用使用数据库? 是的,您需要发布另一个更新。在此更新中,确保您的数据库具有版本表。启动后,检查旧 db 文件是否存在,如果存在,check if it has the new column。如果没有,请通过执行ALTER TABLE ADD COLUMN 等相关命令将其转换为新的模式格式。希望这能澄清。

以上是关于如何在 iOS 中覆盖 SQLite 数据库的主要内容,如果未能解决你的问题,请参考以下文章