iOS SQLite 使用FMDBMigrationManager 進(jìn)行數(shù)據(jù)庫(kù)遷移

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];

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容