iOS APP新版本升級數據庫

我們常常會在APP中使用數據庫,但是由于版本迭代問題,數據庫的結構可能會發生變更,這時候需要對用戶原始數據進行保留。這是一個很正常的需求,有人可能會簡單粗暴的把數據庫刪除,重新創建,把數據重新插進去。如果表很多,里面只有一張表的數據結構發生變化了,這種做法真的好么?下面我會講下我的思路,分享交流下。
簡單的流程分析,共四步:

  • 把要更改結構的那張表 A1 改名為 tempA1
  • 創建一張當前版本需要結構的表A1
  • 將tempA1 里面的有效數據 遷移到 A1中
  • 刪除 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];
}

//V2升級到V3
- (void)v2Tov3{
 [_queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
//和 v1ToV2 流程一樣
 }] ;
 [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithInteger:DBVersionV3] forKey:DBVersionNum];
}

上文提到的數據遷移流程就是如此。
如有更好的方案可以互相交流。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容