FMDBMigrationManager 是與FMDB結(jié)合使用的一個(gè)第三方,可以記錄數(shù)據(jù)庫(kù)版本號(hào)并對(duì)數(shù)據(jù)庫(kù)進(jìn)行數(shù)據(jù)庫(kù)升級(jí)等操作。
首先要集成FMDB和FMDBMigrationManager,建議使用cocoapods,這里不再多說(shuō)。
根據(jù)官方文檔的解釋?zhuān)袃煞N方法實(shí)現(xiàn)升級(jí),我們一個(gè)一個(gè)的解釋。
先說(shuō)第一種,添加文件的方式進(jìn)行記錄版本和升級(jí)操作,新建一個(gè)空白的項(xiàng)目,并創(chuàng)建一個(gè)數(shù)據(jù)庫(kù),也就是我們將要進(jìn)行升級(jí)操作的數(shù)據(jù)庫(kù)。
將數(shù)據(jù)庫(kù)與我們的FMDBMigrationManager關(guān)聯(lián)起來(lái)
FMDBMigrationManager * manager=[FMDBMigrationManager managerWithDatabaseAtPath:DBPath migrationsBundle:[NSBundle mainBundle]];
//DBPath是要升級(jí)的數(shù)據(jù)庫(kù)的地址
// [NSBundle mainBundle]是保存數(shù)據(jù)庫(kù)升級(jí)文件的位置 根據(jù)自己放文件的位置定 升級(jí)文件是什么下面會(huì)說(shuō)
下面創(chuàng)建版本號(hào)表,這個(gè)表會(huì)保存在我們的數(shù)據(jù)庫(kù)中,進(jìn)行數(shù)據(jù)庫(kù)版本號(hào)的記錄,并將我們的數(shù)據(jù)庫(kù)升級(jí)到最高的版本。
BOOL resultState=NO;
NSError * error=nil;
if (!manager.hasMigrationsTable) {
resultState=[manager createMigrationsTable:&error];
}
執(zhí)行完該語(yǔ)句,再去我們的數(shù)據(jù)庫(kù)中查看,會(huì)發(fā)現(xiàn)多了一個(gè)表 schema_migrations

這個(gè)表就是用來(lái)存儲(chǔ)版本號(hào)的,目前表中的版本號(hào)(version)為0。
下面是最重要的升級(jí)語(yǔ)句
BOOL resultState=NO;
resultState=[manager migrateDatabaseToVersion:UINT64_MAX progress:nil error:&error];
//UINT64_MAX 表示升級(jí)到最高版本
整體的升級(jí)函數(shù)就是
FMDBMigrationManager * manager=[FMDBMigrationManager managerWithDatabaseAtPath:DBPath migrationsBundle:[NSBundle mainBundle]];
BOOL resultState=NO;
NSError * error=nil;
if (!manager.hasMigrationsTable) {
resultState=[manager createMigrationsTable:&error];
}
resultState=[manager migrateDatabaseToVersion:UINT64_MAX progress:nil error:&error];
此時(shí)還沒(méi)有添加升級(jí)文件,所以執(zhí)行完這段代碼數(shù)據(jù)庫(kù)并沒(méi)有什么變化,下面添加升級(jí)文件。
所謂升級(jí)文件,就是一些sql文件,在里面寫(xiě)入一些對(duì)數(shù)據(jù)庫(kù)操作的語(yǔ)句

文件名的格式是固定的 (數(shù)字)_(描述性語(yǔ)言).sql,前面的數(shù)字就是所謂的版本號(hào),官方建議使用時(shí)間戳,也可以使用1,2,3,4,5……升級(jí),保持單調(diào)遞增即可。
文件內(nèi)寫(xiě)入要對(duì)數(shù)據(jù)庫(kù)做的操作

然后將文件拖入工程

FMDBMigrationManager 將會(huì)根據(jù)創(chuàng)建時(shí)給入的NSBundle自行尋找sql文件,對(duì)比版本號(hào)進(jìn)行操作。添加sql文件之后,重啟項(xiàng)目,再運(yùn)行一次升級(jí)代碼,查看數(shù)據(jù)庫(kù)

發(fā)現(xiàn)新增了一個(gè)User表,再加入一個(gè)新增數(shù)據(jù)庫(kù)字段的文件(工程中常用的升級(jí)操作就是增加數(shù)據(jù)庫(kù)字段)

2_AddEmail.sql 的內(nèi)容

重啟項(xiàng)目運(yùn)行升級(jí)代碼,查看數(shù)據(jù)庫(kù)

發(fā)現(xiàn)email已經(jīng)添加進(jìn)來(lái)了

存儲(chǔ)的版本號(hào)也已經(jīng)記錄到2了,以后還想升級(jí)的話,再向項(xiàng)目中添加 3_***.sql 文件就好了。
下面使用第二種方法進(jìn)行升級(jí),使用自定義類(lèi)的形式。第一種方法,每次升級(jí)都要建立一個(gè)文件,而且大多數(shù)時(shí)候,文件里面只寫(xiě)一句話,感情上會(huì)難以接受,因此我們介紹一種較為簡(jiǎn)潔的方式。首先定義一個(gè)新的類(lèi):Migration
遵循FMDBMigrating協(xié)議,與第一種拖入文件的方式相同,name是升級(jí)描述,version是版本號(hào),最后一個(gè)方法里面,進(jìn)行操作。
由于name和version都是只讀的,因此我們要自定義一個(gè)init方法,傳入描述 版本號(hào)和升級(jí)語(yǔ)句,升級(jí)語(yǔ)句最好用數(shù)組的方式傳入,因?yàn)榭赡苡卸鄠€(gè)升級(jí)語(yǔ)句。
//
// Migration.h
// Sqlite
//
// Created by LC on 16/10/21.
// Copyright ? 2016年 LC. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "FMDBMigrationManager.h"
@interface Migration : NSObject<FMDBMigrating>
- (instancetype)initWithName:(NSString *)name andVersion:(uint64_t)version andExecuteUpdateArray:(NSArray *)updateArray;//自定義方法
@property (nonatomic, readonly) NSString *name;
@property (nonatomic, readonly) uint64_t version;
- (BOOL)migrateDatabase:(FMDatabase *)database error:(out NSError *__autoreleasing *)error;
@end
//
// Migration.m
// Sqlite
//
// Created by LC on 16/10/21.
// Copyright ? 2016年 LC. All rights reserved.
//
#import "Migration.h"
@interface Migration()
@property(nonatomic,copy)NSString * myName;
@property(nonatomic,assign)uint64_t myVersion;
@property(nonatomic,strong)NSArray * updateArray;
@end
@implementation Migration
- (instancetype)initWithName:(NSString *)name andVersion:(uint64_t)version andExecuteUpdateArray:(NSArray *)updateArray
{
if (self=[super init]) {
_myName=name;
_myVersion=version;
_updateArray=updateArray;
}
return self;
}
- (NSString *)name
{
return _myName;
}
- (uint64_t)version
{
return _myVersion;
}
- (BOOL)migrateDatabase:(FMDatabase *)database error:(out NSError *__autoreleasing *)error
{
for(NSString * updateStr in _updateArray)
{
[database executeUpdate:updateStr];
}
return YES;
}
@end
使用方法也很簡(jiǎn)單,將自定義類(lèi)對(duì)象添加進(jìn)manager即可。
NSString *DBPath = [documents stringByAppendingPathComponent:KFMDBName];
NSLog(@"%@",DBPath);
//DBPath是要升級(jí)的數(shù)據(jù)庫(kù)的地址
// [NSBundle mainBundle]是保存數(shù)據(jù)庫(kù)升級(jí)文件的位置 根據(jù)自己放文件的位置定 升級(jí)文件是什么下面會(huì)說(shuō)
FMDBMigrationManager * manager = [FMDBMigrationManager managerWithDatabaseAtPath:DBPath migrationsBundle:[NSBundle mainBundle]];
Migration * migration_1=[[Migration alloc]initWithName:@"新增USer表" andVersion:1 andExecuteUpdateArray:@[@"create table User(name text,age integer,sex text,phoneNum text)"]];
[manager addMigration:migration_1];
Migration * migration_2=[[Migration alloc]initWithName:@"USer表新增字段email" andVersion:2 andExecuteUpdateArray:@[@"alter table User add email text"]];
[manager addMigration:migration_2];
BOOL resultState=NO;
NSError * error=nil;
if (!manager.hasMigrationsTable) {
resultState=[manager createMigrationsTable:&error];
}
//UINT64_MAX 表示升級(jí)到最高版本
resultState=[manager migrateDatabaseToVersion:UINT64_MAX progress:nil error:&error];
NSLog(@"Has `schema_migrations` table?: %@", manager.hasMigrationsTable ? @"YES" : @"NO");
NSLog(@"Origin Version: %llu", manager.originVersion);
NSLog(@"Current version: %llu", manager.currentVersion);
NSLog(@"All migrations: %@", manager.migrations);
NSLog(@"Applied versions: %@", manager.appliedVersions);
NSLog(@"Pending versions: %@", manager.pendingVersions);
以后還想升級(jí),在加入一個(gè)新的自定義對(duì)象,注意?。?!版本號(hào)要保持遞增
NSString *DBPath = [documents stringByAppendingPathComponent:KFMDBName];
NSLog(@"%@",DBPath);
//DBPath是要升級(jí)的數(shù)據(jù)庫(kù)的地址
// [NSBundle mainBundle]是保存數(shù)據(jù)庫(kù)升級(jí)文件的位置 根據(jù)自己放文件的位置定 升級(jí)文件是什么下面會(huì)說(shuō)
FMDBMigrationManager * manager = [FMDBMigrationManager managerWithDatabaseAtPath:DBPath migrationsBundle:[NSBundle mainBundle]];
Migration * migration_1=[[Migration alloc]initWithName:@"新增USer表" andVersion:1 andExecuteUpdateArray:@[@"create table User(name text,age integer,sex text,phoneNum text)"]];
[manager addMigration:migration_1];
Migration * migration_2=[[Migration alloc]initWithName:@"USer表新增字段email" andVersion:2 andExecuteUpdateArray:@[@"alter table User add email text"]];
[manager addMigration:migration_2];
Migration * migration_3=[[Migration alloc]initWithName:@"USer表新增字段address" andVersion:3 andExecuteUpdateArray:@[@"alter table User add address text"]];
[manager addMigration:migration_3];
BOOL resultState=NO;
NSError * error=nil;
if (!manager.hasMigrationsTable) {
resultState=[manager createMigrationsTable:&error];
}
//UINT64_MAX 表示升級(jí)到最高版本
resultState=[manager migrateDatabaseToVersion:UINT64_MAX progress:nil error:&error];