Just Curious给出的答案非常正确(你明白我的意思了!),它就是我们用来跟踪应用程序中当前数据库模式版本的工具。 为了运行需要执行的迁移,以使user_version与应用的预期架构版本相匹配,我们使用了switch语句。下面是应用Strip中的一个剪切示例:
- (void) migrateToSchemaFromVersion:(NSInteger)fromVersion toVersion:(NSInteger)toVersion {
// allow migrations to fall thru switch cases to do a complete run
// start with current version + 1
[self beginTransaction];
switch (fromVersion + 1) {
case 3:
// change pin type to mode 'pin' for keyboard handling changes
// removing types from previous schema
sqlite3_exec(db, "DELETE FROM types;", NULL, NULL, NULL);
NSLog(@"installing current types");
[self loadInitialData];
case 4:
//adds support for recent view tracking
sqlite3_exec(db, "ALTER TABLE entries ADD COLUMN touched_at TEXT;", NULL, NULL, NULL);
case 5:
{
sqlite3_exec(db, "ALTER TABLE categories ADD COLUMN image TEXT;", NULL, NULL, NULL);
sqlite3_exec(db, "ALTER TABLE categories ADD COLUMN entry_count INTEGER;", NULL, NULL, NULL);
sqlite3_exec(db, "CREATE INDEX IF NOT EXISTS categories_id_idx ON categories(id);", NULL, NULL, NULL);
sqlite3_exec(db, "CREATE INDEX IF NOT EXISTS categories_name_id ON categories(name);", NULL, NULL, NULL);
sqlite3_exec(db, "CREATE INDEX IF NOT EXISTS entries_id_idx ON entries(id);", NULL, NULL, NULL);
// etc...
}
}
[self setSchemaVersion];
[self endTransaction];
}
- (void)upgradeDatabaseIfNeeded {
if ([self databaseSchemaVersion] < 3)
{
if ([self databaseSchemaVersion] < 2)
{
if ([self databaseSchemaVersion] < 1)
{
// run statements to upgrade from 0 to 1
}
// run statements to upgrade from 1 to 2
}
// run statements to upgrade from 2 to 3
// and so on...
// set this to the latest version number
[self setDatabaseSchemaVersion:3];
}
}
9条答案
按热度按时间xqkwcwgp1#
我维护了一个应用程序,它需要定期更新sqlite数据库并将旧数据库迁移到新模式,下面是我所做的:
为了跟踪数据库版本,我使用了sqlite提供的内置user-version变量(sqlite对这个变量不做任何处理,你可以随意使用它),它从0开始,你可以用下面的sqlite语句来获取/设置这个变量:
当应用程序启动时,我检查当前的用户版本,应用使模式最新所需的任何更改,然后更新用户版本。我将更新 Package 在一个事务中,这样如果出现任何错误,更改都不会提交。
对于模式更改,sqlite支持使用“ALTER TABLE”语法进行某些操作(重命名表或添加列)。这是就地更新现有表的简单方法。请参阅此处的文档:为了删除“ALTER TABLE”语法不支持的列或其他更改,我创建了一个新表,将日期迁移到其中,删除旧表,并将新表重命名为原来的名称。
bvpmtnay2#
Just Curious给出的答案非常正确(你明白我的意思了!),它就是我们用来跟踪应用程序中当前数据库模式版本的工具。
为了运行需要执行的迁移,以使user_version与应用的预期架构版本相匹配,我们使用了switch语句。下面是应用Strip中的一个剪切示例:
eulz3vhy3#
让我分享一些FMDB和MBProgressHUD的迁移代码。
下面是如何读写模式版本号(这可能是模型类的一部分,在我的例子中,它是一个名为Database的单例类):
下面是延迟打开数据库的
[self database]
方法:下面是从视图控制器调用的迁移方法:
下面是调用迁移的根视图控制器代码,使用MBProgressHUD显示进度面板:
a64a0gku4#
1
。创建包含基于SQL的迁移列表的/migrations
文件夹,其中每个迁移类似于:/migrations/001-categories.sql
/migrations/002-posts.sql
2
。创建包含已应用迁移列表的db表,例如:3
。更新应用程序引导逻辑,使其在启动之前从/migrations
文件夹获取迁移列表,并运行尚未应用的迁移。下面是一个使用JavaScript实现的示例:SQLite Client for Node.js Apps
pgccezyw5#
IMO最好的解决方案是建立一个SQLite升级框架。我也有同样的问题(在C#世界),我建立了自己的这样的框架。你可以阅读here。它完美地工作,使我(以前噩梦般的)升级工作在我这边最小的努力。
尽管这个库是用C#实现的,但是这里介绍的思想在您的情况下也应该可以很好地工作。
iklwldmw6#
一些提示...
1)我建议将所有用于迁移数据库的代码放到一个NSOperation中,并在后台线程中运行它。当数据库被迁移时,您可以显示一个带有微调器的自定义UIAlertView。
2)请确保将数据库从捆绑包复制到应用的文档中,并从该位置使用它,否则每次应用更新都会覆盖整个数据库,然后迁移新的空数据库。
3)FMDB很棒,但是它的executeQuery方法由于某种原因不能执行PRAGMA查询,如果你想使用PRAGMA user_version检查模式版本,你需要编写自己的方法直接使用sqlite3。
4)此代码结构将确保您的更新按顺序执行,并且无论用户在应用更新之间间隔多长时间,所有更新都将执行。它可以进一步重构,但这是一种非常简单的查看方式。每次示例化数据单例时,都可以安全地运行此方法。并且只需要一个很小的数据库查询,如果正确地设置了数据单例,每个会话只发生一次。
f45qwnt87#
对于.net,您可以使用lib:
EntityFrameworkCore.Sqlite.Migrations
它很简单,所以对于任何其他平台,您都可以轻松实现与lib中相同的行为。
hfwmuf9z8#
如果您更改数据库模式和所有使用该模式的代码,就像嵌入式应用程序和手机应用程序中的情况一样,问题实际上可以得到很好的控制(没有什么比得上企业数据库上的模式迁移噩梦,该数据库可能服务于数百个应用程序--也不是所有应用程序都在DBA的控制之下; -).
iyr7buue9#
在我的文章Simple declarative schema migration for SQLite中,我们通过创建一个原始的内存数据库,并通过查询“sqlite_schema”表将该模式与当前数据库进行比较来自动地计算模式更改,然后我们按照SQLite文档中的12步过程来安全地修改表。
您可以按照自己的喜好定义模式(ORM或纯SQL“CREATE TABLE”语句等),只要您可以使用它来创建新的内存数据库。这意味着您只需在一个位置维护模式,并且在应用程序启动时自动应用更改。
当然也有局限性--特别是它不能处理数据迁移,只能处理模式迁移;并且新列必须允许空值或指定默认值,但总的来说,使用它是一件愉快的事情。