iOS APP新版本升級數(shù)據(jù)庫

原文
iOS APP新版本升級數(shù)據(jù)庫

我們常常會(huì)在APP中使用數(shù)據(jù)庫,但是由于版本迭代問題,數(shù)據(jù)庫的結(jié)構(gòu)可能會(huì)發(fā)生變更,這時(shí)候需要對用戶原始數(shù)據(jù)進(jìn)行保留。這是一個(gè)很正常的需求,有人可能會(huì)簡單粗暴的把數(shù)據(jù)庫刪除,重新創(chuàng)建,把數(shù)據(jù)重新插進(jìn)去。如果表很多,里面只有一張表的數(shù)據(jù)結(jié)構(gòu)發(fā)生變化了,這種做法真的好么?下面我會(huì)講下我的思路,分享交流下。
簡單的流程分析,共四步:
1 把要更改結(jié)構(gòu)的那張表 A1 改名為 tempA1
2 創(chuàng)建一張當(dāng)前版本需要結(jié)構(gòu)的表A1
3 將tempA1 里面的有效數(shù)據(jù) 遷移到 A1中
4 刪除 tempA1
以上簡單的思路數(shù)據(jù)庫就更改完畢了。
這時(shí)引出了第二個(gè)問題,如果用戶的app沒有及時(shí)更新,錯(cuò)過了好幾個(gè)版本的數(shù)據(jù)庫更改,以上數(shù)據(jù)庫更改不可能會(huì)一步到位了?;啚榉?,一步一步的更改數(shù)據(jù)庫表結(jié)構(gòu),直到更改到最后一次。下面看代碼。

typedef NS_ENUM(NSInteger, DBVersion) {
    DBVersionV1,
    DBVersionV2,    //歷史版本
    DBVersionV3,    //當(dāng)前版本
};

static NSString *const DBVersionNum  = @"DBVersionNum";
static NSString *const dbPath = @"\tmp\tmp.db";     //數(shù)據(jù)庫地址

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')))";

首先定義了一個(gè)枚舉,標(biāo)識(shí)著當(dāng)前一共有多少數(shù)據(jù)庫版本變更。(客戶端數(shù)據(jù)庫結(jié)構(gòu)更改不會(huì)太頻繁,如果更改太快,可能意味著初期表設(shè)計(jì)不合理),此次模擬共三個(gè)版本的數(shù)據(jù)庫。

- (instancetype)init{
    if (self = [super init]) {
        _queue = [FMDatabaseQueue databaseQueueWithPath:dbPath];
    }
    return self;
}

采用FMDatabaseQueue 進(jìn)行數(shù)據(jù)庫操作的管理。

/*
 *  需要初始化表結(jié)構(gòu)時(shí),調(diào)用此方法
 */
- (void)newDBVersionInit{
    if (![[NSUserDefaults standardUserDefaults] objectForKey:DBVersionNum]) {
        //系統(tǒng)之前沒有數(shù)據(jù)庫 新建立表。
        [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系統(tǒng)之前是否存儲(chǔ)過,
沒有存儲(chǔ)說明是第一次安裝,則進(jìn)行首次創(chuàng)建表處理。
有說明之前數(shù)據(jù)庫存在,進(jìn)行數(shù)據(jù)庫表結(jié)構(gòu)更改。如果是v1版本的數(shù)據(jù)庫 先從v1升級到v2,在從v2升級到v3,以此類推。

/*
 *  創(chuàng)建新表
 */
- (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 數(shù)據(jù)遷移
 */
- (void)v1ToV2{
    
    [_queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
        @try {
            
            //將原始表名T1 修改為 tempT1
            NSString *renameString = @"alter table t1 rename to tempT1";
            [db executeUpdate:renameString];
            
            //創(chuàng)建新表T1(V2版本的新表創(chuàng)建)
            [db executeUpdate:createTable];
            
            //遷移數(shù)據(jù)
            NSString *toString = @"insert into t1(name,sex)  select name,sex from tempT1";
            [db executeUpdate:toString];
            
            //刪除tempT1臨時(shí)表
            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];
}

上文提到的數(shù)據(jù)遷移流程就是如此。

參考文章:
iOS APP新版本升級數(shù)據(jù)庫
iOS數(shù)據(jù)庫版本升級問題

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

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

  • 我們常常會(huì)在APP中使用數(shù)據(jù)庫,但是由于版本迭代問題,數(shù)據(jù)庫的結(jié)構(gòu)可能會(huì)發(fā)生變更,這時(shí)候需要對用戶原始數(shù)據(jù)進(jìn)行保留...
    so_what閱讀 606評論 3 3
  • 用到的組件 1、通過CocoaPods安裝 2、第三方類庫安裝 3、第三方服務(wù) 友盟社會(huì)化分享組件 友盟用戶反饋 ...
    SunnyLeong閱讀 15,191評論 1 180
  • 我陪你從長發(fā)到短發(fā) 你陪我從短發(fā)到長發(fā) 陪彼此過每一個(gè)生日 等我有錢了一定帶你吃香的喝辣的 生日快樂我的小婊貝 愿...
    陌林夕閱讀 157評論 0 0
  • 我小時(shí)候的每個(gè)假期,都是在奶奶家的山間度過,在山間的童年,充滿了快樂的回憶。而如今,生活在鋼筋水泥的城市,在閑暇時(shí)...
    曉蕓will閱讀 573評論 3 6
  • 世界之灰暗 人心不古 飛鳥蹦斷雙翅 走獸吼裂蒼老的嗓子 人猿披著頭發(fā)壯實(shí)如泰山 蒼穹在我身后顛倒黑白 大地萎靡山水...
    青三木閱讀 243評論 0 1

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