FMDB数据库的升级

一、数据库的升级
FMDB的数据迁移用FMDBMigrationManager这个工具类,FMDBMigrationManager 是与FMDB结合使用的一个第三方类库,可以记录数据库版本号并对数据库进行数据库升级等操作。
1、FMDB数据库升级有二种方式:
第一种、添加文件的方式进行记录版本和升级操作,先关联FMDBMigrationManager,再创建数据库升级文件,最后升级。
第二种、使用自定义类的形式进行迁移。先关联FMDBMigrationManager,再创建自定义类,并且遵循FMDBMigrationManager协议,最后把创建的自定义的类型加入到FMDBMigrationManager中,升级。
使用FMDBMigrationManager去
注意:上述两种数据库的升级方式都需要自己写sql语句。这就意味着,你需要熟练使用sql命令。


 第一种:数据库升级的步骤:

1、集成FMDBMigrationManager
可以使用cocoapods或者手动集成


2、将要升级的的数据库和FMDBMigrationManager关联起来
   注意:oldPath 要升级数据库的路径
FMDBMigrationManager * manager=[FMDBMigrationManager managerWithDatabaseAtPath:oldPath migrationsBundle:[NSBundle mainBundle]]; 
BOOL resultState=NO; 
NSError * error=nil; 
if (!manager.hasMigrationsTable) { 
resultState=[manager createMigrationsTable:&;error]; 
} 



执行了上面的代码以后,会发现多了一个 schema_migrations的表。
这个表是用来存储版本号的,现在表中的版本号(version)为0 ,rowid是升级文件“_”前面的数字。

 注意:
下面这句代码是升级数据库的主要代码
 UINT64_MAX 表示升级到最高版本

resultState=[manager migrateDatabaseToVersion:UINT64_MAX progress:nil error:&;error]; 
3、创建升级文件(sql文件)
我们说的升级文件就是sql文件,里面写的是数据库操作的sql语句.
sql文件的文件名的格式都是是固定的 (数字)_(描述性语言).sql,最前面的数字就是版本号,可以使用1,2,3,4,5……升级,保持单调递增即可;也可以使用时间戳,官方建议使用时间戳,sql文件内写入要对数据库做的操作的sql语句。
注意:
可以命令行创建相应的sql文件,XXXXXXXXXXXXX是描述性语言。

$ touch "`ruby -e "puts Time.now.strftime('%Y%m%d%H%M%S%3N').to_i"`"_XXXXXXXXXXXXX.sql





然后把sql文件拖入我们的工程中




这时FMDBMigrationManager将会根据创建时给入的NSBundle自行寻找sql文件,进行版本号对比操作。添加sql文件之后,重启该项目,再运行一次升级代码,这时查看数据库,这时你就会发现刚刚在sql文件中创建的Student表了。
如果你想在Student表中添加一个新的字段,可以再添加一个sql文件,在里面写上你需要执行的sql命令,再把这个文件拖入工程中。重新启动项目,这时,你就会发现你的Student表中多了一个number字段。


现在存储的版本号是2了。如果你想升级成3,只要创建3_XXXXX.sql文件,在sql文件中写相应操作的sql语句就可以了。4、5、6等以此类推,也是使用时间戳来代替。
fmdb的升级方式和coredata的升级方式有点类似,fmdb是创建相应版本的sql文件,coredata是创建相应版本的XXXX.xcdatamodeld。


注意:其实升级的主要方式是逐级升级,如果当前版本是2,现在要升级到版本5,这样他会先升级到3,再从3升级到4,最后在升级到最终的版本5.

schema_migrations表中记录的是你已经迁移成功的数据库版本和对应的sql文件


 第二种方式:使用自定义类的形式进行迁移。先关联FMDBMigrationManager,再创建自定义类型,并且遵循FMDBMigrationManager协议,最后把创建的自定义的类型加入到FMDBMigrationManager中,升级。


创建一个类,需要遵循FMDBMigrating协议

@interface StudentMigration : NSObject<FMDBMigrating>
@property (nonatomic, readonly) NSString *name;
@property (nonatomic, readonly) uint64_t version;
- (instancetype)initWithName:(NSString *)name  version:(uint64_t)version executeUpdateArray:(NSArray *)updateArray;


- (BOOL)studentrMigrateDatabase:(FMDatabase *)database error:(out NSError *__autoreleasing *)error;


@end

@interface StudentMigration()
@property(nonatomic,copy)NSString * mName;
@property(nonatomic,assign)uint64_t mVersion;
@property(nonatomic,strong)NSArray * mUpdateArray;
@end


@implementation StudentMigration
- (instancetype)initWithName:(NSString *)name version:(uint64_t)version executeUpdateArray:(NSArray *)updateArray
{
    if (self=[super init]) {
        _mName=name;
        _mVersion=version;
        _mUpdateArray=updateArray;
    }
    return self;
}
- (NSString *)name
{
    return _mName;
}
- (uint64_t)version
{
    return _mVersion;
}
- (BOOL)studentMigrateDatabase:(FMDatabase *)database error:(out NSError *__autoreleasing *)error
{
    for(NSString * updateStr in _mUpdateArray)
    {
        [database executeUpdate:updateStr];
    }
    return YES;
}


@end

然后将自定义的对象添加进入FMDBMigrationManager类里面,进行升级操作
注意:
 1、这里不需要创建很多的自定义类来升级数据库,只需要创建一个自定义类来实现数据库的升级。通过不同的自定义对象,来实现数据库的升级。比如下面的代码中定义了migrationOne和migrationTwo对象来实现了2个版本的升级。如果需要升级版本3,你需要在定义一个migrationThree对象,version传递3就可以了。
 2、migrationOne和migrationTwo对象中的版本号(version)需要递增。executeUpdateArray这个数组可以传递多个升级语句。Name是每个版本的升级描述。

    //oldPath是要升级的数据库的地址
    NSString *oldPath = KFMDBName;
    FMDBMigrationManager * manager = [FMDBMigrationManager managerWithDatabaseAtPath:oldPath migrationsBundle:[NSBundle mainBundle]];
    StudentMigration * migrationOne=[[UserMigration alloc]initWithName:@"新创建Student表" version:1 executeUpdateArray:@[@"create table Student(name text,age integer,nick text)"]];
    [manager addMigration:migrationOne];
    StudentMigration * migrationTwo=[[UserMigration alloc]initWithName:@"Student表新增number" version:2 executeUpdateArray:@[@"alter table Student add number text"]];
    [manager addMigration:migrationTwo];
    BOOL resultState=NO;
    NSError * error=nil;
    if (!manager.hasMigrationsTable) {
        resultState=[manager createMigrationsTable:&error];
    }
    //UINT64_MAX 表示升级到最高版本
    resultState=[manager migrateDatabaseToVersion:UINT64_MAX progress:nil error:&error];

一个对象可以执行多个sql语句:
//一个对象执行升级多个SQL语句
    StudentMigration * migrationThree=[[UserMigration alloc]initWithName:@"新创建teacher表,Student表新增Sex" version:3 executeUpdateArray:@[@"alter table Student add Sex text",@"create table teacher(name text,age integer,nick text)"]];
    [manager addMigration:migrationThree];

二、遇到的问题
1、FMDB迁移数据的问题
a、一定要明确每个版本的版本号,不然会造成数据升级失败,程序奔溃

比如:之前升级了版本1、2、4、5版本了,这时候你的版本号添加的版本号是3,版本3中添加的一个字段number字段。可是,你的版本号不是逐级递增的,这样就会导致版本3迁移失败,还是原来的版本5,其他类中在使用number这个字段发现该字段并不存在。


三、参考文件

FMDB数据库的迁移 ------https://www.jianshu.com/p/736b00b3a1e1

FMDBMigrationManager下载,使用说明 https://github.com/layerhq/FMDBMigrationManager/blob/master/README.md


四、结束语

本文是介绍了FMDB数据库二种升级的方式,如果有侵权或者写的不好的地方,请留言,我会及时修改。谢谢大家。

猜你喜欢

转载自blog.csdn.net/u014644610/article/details/80241024