如何在 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 数据库的主要内容,如果未能解决你的问题,请参考以下文章

如何获取存储在 iOS 持久性 sqlite 数据库中的值?

如何在 iOS 上拍照并保存在 SQLite 数据库中

在iOS中启动应用程序时如何复制sqlite数据库?

我们如何在Android中重用已经在IOS中创建的Sqlite文件[重复]

如何使用 swift 在 iOS coredata sqlite 中启用 DELETE MODE

如何在使用 sqlite 的 ios 应用程序中使用“已提交”隔离级别?