iOS APP新版本升级数据库
2016-03-15 10:24
363 查看
我们常常会在APP中使用数据库,但是由于版本迭代问题,数据库的结构可能会发生变更,这时候需要对用户原始数据进行保留。这是一个很正常的需求,有人可能会简单粗暴的把数据库删除,重新创建,把数据重新插进去。如果表很多,里面只有一张表的数据结构发生变化了,这种做法真的好么?下面我会讲下我的思路,分享交流下。
简单的流程分析,共四步:
1 把要更改结构的那张表 A1 改名为 tempA1
2 创建一张当前版本需要结构的表A1
3 将tempA1 里面的有效数据 迁移到 A1中
4 删除 tempA1
以上简单的思路数据库就更改完毕了。
这时引出了第二个问题,如果用户的app没有及时更新,错过了好几个版本的数据库更改,以上数据库更改不可能会一步到位了。化简为繁,一步一步的更改数据库表结构,直到更改到最后一次。下面看代码。
首先定义了一个枚举,标识着当前一共有多少数据库版本变更。(客户端数据库结构更改不会太频繁,如果更改太快,可能意味着初期表设计不合理),此次模拟共三个版本的数据库。
采用FMDatabaseQueue 进行数据库操作的管理。
在这里判断DBVersionNum系统之前是否存储过,
没有存储说明是第一次安装,则进行首次创建表处理。
有说明之前数据库存在,进行数据库表结构更改。如果是v1版本的数据库 先从v1升级到v2,在从v2升级到v3,以此类推。
把 DBVersionNum的值写为V3版本 方便下次对比。
上文提到的数据迁移流程就是如此。
简单的流程分析,共四步:
1 把要更改结构的那张表 A1 改名为 tempA1
2 创建一张当前版本需要结构的表A1
3 将tempA1 里面的有效数据 迁移到 A1中
4 删除 tempA1
以上简单的思路数据库就更改完毕了。
这时引出了第二个问题,如果用户的app没有及时更新,错过了好几个版本的数据库更改,以上数据库更改不可能会一步到位了。化简为繁,一步一步的更改数据库表结构,直到更改到最后一次。下面看代码。
typedef NS_ENUM(NSInteger, DBVersion) { DBVersionV1, DBVersionV2, //历史版本 DBVersionV3, //当前版本 }; static NSString *const DBVersionNum = @"DBVersionNum"; static NSString *const dbPath = @"\tmp\tmp.db"; //数据库地址 static NSString *const createTable = @"create table if not exists t1(" "id integer PRIMARY KEY AUTOINCREMENT NOT NULL," "name char(50)," "sex char(4)," "recordDate TIMESTAMP default (datetime('now', 'localtime')))";
首先定义了一个枚举,标识着当前一共有多少数据库版本变更。(客户端数据库结构更改不会太频繁,如果更改太快,可能意味着初期表设计不合理),此次模拟共三个版本的数据库。
- (instancetype)init{ if (self = [super init]) { _queue = [FMDatabaseQueue databaseQueueWithPath:dbPath]; } return self; }
采用FMDatabaseQueue 进行数据库操作的管理。
/* * 需要初始化表结构时,调用此方法 */ - (void)newDBVersionInit{ if (![[NSUserDefaults standardUserDefaults] objectForKey:DBVersionNum]) { //系统之前没有数据库 新建立表。 [self createTables]; }else{ DBVersion ver = [[[NSUserDefaults standardUserDefaults] objectForKey:DBVersionNum] integerValue]; switch (ver) { case DBVersionV1:{ [self v1ToV2]; } case DBVersionV2:{ [self v2Tov3]; } case DBVersionV3:{ } break; default: break; } } }
在这里判断DBVersionNum系统之前是否存储过,
没有存储说明是第一次安装,则进行首次创建表处理。
有说明之前数据库存在,进行数据库表结构更改。如果是v1版本的数据库 先从v1升级到v2,在从v2升级到v3,以此类推。
/* * 创建新表 */ - (void)createTables{ [_queue inTransaction:^(FMDatabase *db, BOOL *rollback) { @try { [db executeUpdate:createTable]; } @catch (NSException *exception) { *rollback = YES; } }]; [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInteger:DBVersionV3] forKey:DBVersionNum]; }
把 DBVersionNum的值写为V3版本 方便下次对比。
/* * 版本1 向 版本2 数据迁移 */ - (void)v1ToV2{ [_queue inTransaction:^(FMDatabase *db, BOOL *rollback) { @try { //将原始表名T1 修改为 tempT1 NSString *renameString = @"alter table t1 rename to tempT1"; [db executeUpdate:renameString]; //创建新表T1(V2版本的新表创建) [db executeUpdate:createTable]; //迁移数据 NSString *toString = @"insert into t1(name,sex) select name,sex from tempT1"; [db executeUpdate:toString]; //删除tempT1临时表 NSString *dropTableStr1 = @"drop table tempT1"; [db executeUpdate:dropTableStr1]; } @catch (NSException *exception) { *rollback = YES; } }] ; [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInteger:DBVersionV2] forKey:DBVersionNum]; } - (void)v2Tov3{ [_queue inTransaction:^(FMDatabase *db, BOOL *rollback) { //和 v1ToV2 流程一样 }] ; [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInteger:DBVersionV3] forKey:DBVersionNum]; }
上文提到的数据迁移流程就是如此。
相关文章推荐
- iOS 取消延时执行 performSelector: withObject: afterDelay:
- android:configChanges="orientation" 不起作用
- Android EditTexit设置最大长度 中文按2个字符计算
- 《千万别说swift不用管理内存!这么多坑赶快记下》
- android软件服务器的一些想法
- Android Volley解析(二)之表单提交篇
- Android开发性能优化大总结
- android listview用adapter.notifyDataSetChanged()无法刷新每项的图标
- Cocos2d-x 3.1.1 学习日志5--cocos2d-x3.1.1打飞机的实现
- Android Volley解析(一)之GET、POST请求篇
- Android 生成文字图片验证码
- iOS中assign,copy,retain之间的区别以及weak和strong的区别
- unity terrain export to obj
- android-cts兼容性自动化测试
- Swift的两个小窍门
- iOS 定时器的比较
- iOS二维码生成及扫码
- iOS AutoLayout使用心得
- Systemv 和Posix的主要功能和定义
- Xcode TODO MARK FIXME 标记