我正在为我的iphone使用sqlite,我预计数据库架构可能会随着时间而改变.每次成功迁移时需要注意的问题,命名约定和注意事项是什么?
例如,我曾想过将一个版本附加到数据库名称(例如Database_v1).
Rng*_*bus 103
我维护一个应用程序,它定期需要更新sqlite数据库并将旧数据库迁移到新模式,这就是我的工作:
为了跟踪数据库版本,我使用sqlite提供的内置用户版本变量(sqlite对此变量不执行任何操作,您可以随意使用它).它从0开始,您可以使用以下sqlite语句获取/设置此变量:
> PRAGMA user_version;
> PRAGMA user_version = 1;
Run Code Online (Sandbox Code Playgroud)
当应用程序启动时,我会检查当前的用户版本,应用使架构更新所需的任何更改,然后更新用户版本.我将更新包装在事务中,以便在出现任何错误时,不会提交更改.
为了进行模式更改,sqlite支持某些操作的"ALTER TABLE"语法(重命名表或添加列).这是一种就地更新现有表的简便方法.请参阅此处的文档:http://www.sqlite.org/lang_altertable.html.为了删除"ALTER TABLE"语法不支持的列或其他更改,我创建了一个新表,将日期迁移到其中,删除旧表,并将新表重命名为原始名称.
Bil*_*ray 29
Just Curious的答案是死的(你明白我的意思!),这就是我们用来跟踪应用程序中当前数据库架构的版本.
要运行需要发生的迁移以使user_version与应用程序的预期模式版本匹配,我们使用switch语句.以下是我们的应用条带中的外观示例:
- (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];
}
Run Code Online (Sandbox Code Playgroud)
And*_*sov 20
让我与FMDB和MBProgressHUD共享一些迁移代码.
这是你如何读取和编写模式版本号(这可能是模型类的一部分,在我的例子中,它是一个名为Database的单例类):
- (int)databaseSchemaVersion {
FMResultSet *resultSet = [[self database] executeQuery:@"PRAGMA user_version"];
int version = 0;
if ([resultSet next]) {
version = [resultSet intForColumnIndex:0];
}
return version;
}
- (void)setDatabaseSchemaVersion:(int)version {
// FMDB cannot execute this query because FMDB tries to use prepared statements
sqlite3_exec([self database].sqliteHandle, [[NSString stringWithFormat:@"PRAGMA user_version = %d", DatabaseSchemaVersionLatest] UTF8String], NULL, NULL, NULL);
}
Run Code Online (Sandbox Code Playgroud)
这[self database]是懒惰地打开数据库的方法:
- (FMDatabase *)database {
if (!_databaseOpen) {
_databaseOpen = YES;
NSString *documentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *databaseName = [NSString stringWithFormat:@"userdata.sqlite"];
_database = [[FMDatabase alloc] initWithPath:[documentsDir stringByAppendingPathComponent:databaseName]];
_database.logsErrors = YES;
if (![_database openWithFlags:SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FILEPROTECTION_COMPLETE]) {
_database = nil;
} else {
NSLog(@"Database schema version is %d", [self databaseSchemaVersion]);
}
}
return _database;
}
Run Code Online (Sandbox Code Playgroud)
以下是从视图控制器调用的迁移方法:
- (BOOL)databaseNeedsMigration {
return [self databaseSchemaVersion] < databaseSchemaVersionLatest;
}
- (void)migrateDatabase {
int version = [self databaseSchemaVersion];
if (version >= databaseSchemaVersionLatest)
return;
NSLog(@"Migrating database schema from version %d to version %d", version, databaseSchemaVersionLatest);
// ...the actual migration code...
if (version < 1) {
[[self database] executeUpdate:@"CREATE TABLE foo (...)"];
}
[self setDatabaseSchemaVersion:DatabaseSchemaVersionLatest];
NSLog(@"Database schema version after migration is %d", [self databaseSchemaVersion]);
}
Run Code Online (Sandbox Code Playgroud)
这是调用迁移的根视图控制器代码,使用MBProgressHUD显示进度边框:
- (void)viewDidAppear {
[super viewDidAppear];
if ([[Database sharedDatabase] userDatabaseNeedsMigration]) {
MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView:self.view.window];
[self.view.window addSubview:hud];
hud.removeFromSuperViewOnHide = YES;
hud.graceTime = 0.2;
hud.minShowTime = 0.5;
hud.labelText = @"Upgrading data";
hud.taskInProgress = YES;
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[hud showAnimated:YES whileExecutingBlock:^{
[[Database sharedDatabase] migrateUserDatabase];
} onQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0) completionBlock:^{
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
}];
}
}
Run Code Online (Sandbox Code Playgroud)
1. /migrations使用基于 SQL 的迁移列表创建文件夹,其中每个迁移如下所示:
/migrations/001-categories.sql
-- Up
CREATE TABLE Category (id INTEGER PRIMARY KEY, name TEXT);
INSERT INTO Category (id, name) VALUES (1, 'Test');
-- Down
DROP TABLE User;
Run Code Online (Sandbox Code Playgroud)
/migrations/002-posts.sql
-- Up
CREATE TABLE Post (id INTEGER PRIMARY KEY, categoryId INTEGER, text TEXT);
-- Down
DROP TABLE Post;
Run Code Online (Sandbox Code Playgroud)
2. 创建包含已应用迁移列表的 db 表,例如:
CREATE TABLE Migration (name TEXT);
Run Code Online (Sandbox Code Playgroud)
3. 更新应用程序引导逻辑,以便在启动之前从/migrations文件夹中获取迁移列表并运行尚未应用的迁移。
下面是一个用 JavaScript 实现的例子:SQLite Client for Node.js Apps
| 归档时间: |
|
| 查看次数: |
33870 次 |
| 最近记录: |