亚洲综合原千岁中文字幕_国产精品99久久久久久久vr_无码人妻aⅴ一区二区三区浪潮_成人h动漫精品一区二区三

主頁 > 知識(shí)庫 > IOS 數(shù)據(jù)庫升級(jí)數(shù)據(jù)遷移的實(shí)例詳解

IOS 數(shù)據(jù)庫升級(jí)數(shù)據(jù)遷移的實(shí)例詳解

熱門標(biāo)簽:寧波企業(yè)外呼系統(tǒng)收費(fèi) 上海智能外呼系統(tǒng)代理商 成都優(yōu)派外呼系統(tǒng) 地圖標(biāo)注人員兼職 扎樣申請(qǐng)400電話 ps制作地圖標(biāo)注gif 電子地圖標(biāo)注電話 聊城智能外呼系統(tǒng)運(yùn)營(yíng)商 沈陽電銷外呼系統(tǒng)原理是什么

IOS 數(shù)據(jù)庫升級(jí)數(shù)據(jù)遷移的實(shí)例詳解

概要:

很久以前就遇到過數(shù)據(jù)庫版本升級(jí)的引用場(chǎng)景,當(dāng)時(shí)的做法是簡(jiǎn)單的刪除舊的數(shù)據(jù)庫文件,重建數(shù)據(jù)庫和表結(jié)構(gòu),這種暴力升級(jí)的方式會(huì)導(dǎo)致舊的數(shù)據(jù)的丟失,現(xiàn)在看來這并不不是一個(gè)優(yōu)雅的解決方案,現(xiàn)在一個(gè)新的項(xiàng)目中又使用到了數(shù)據(jù)庫,我不得不重新考慮這個(gè)問題,我希望用一種比較優(yōu)雅的方式去解決這個(gè)問題,以后我們還會(huì)遇到類似的場(chǎng)景,我們都想做的更好不是嗎?

理想的情況是:數(shù)據(jù)庫升級(jí),表結(jié)構(gòu)、主鍵和約束有變化,新的表結(jié)構(gòu)建立之后會(huì)自動(dòng)的從舊的表檢索數(shù)據(jù),相同的字段進(jìn)行映射遷移數(shù)據(jù),而絕大多數(shù)的業(yè)務(wù)場(chǎng)景下的數(shù)據(jù)庫版本升級(jí)是只涉及到字段的增減、修改主鍵約束,所以下面要實(shí)現(xiàn)的方案也是從最基本的、最常用的業(yè)務(wù)場(chǎng)景去做一個(gè)實(shí)現(xiàn),至于更加復(fù)雜的場(chǎng)景,可以在此基礎(chǔ)上進(jìn)行擴(kuò)展,達(dá)到符合自己的預(yù)期的。

選型定型

網(wǎng)上搜索了下,并沒有數(shù)據(jù)庫升級(jí)數(shù)據(jù)遷移簡(jiǎn)單完整的解決方案,找到了一些思路

1.清除舊的數(shù)據(jù),重建表

優(yōu)點(diǎn):簡(jiǎn)單
缺點(diǎn):數(shù)據(jù)丟失

2.在已有表的基礎(chǔ)上對(duì)表結(jié)構(gòu)進(jìn)行修改

優(yōu)點(diǎn):能夠保留數(shù)據(jù)
缺點(diǎn):規(guī)則比較繁瑣,要建立一個(gè)數(shù)據(jù)庫的字段配置文件,然后讀取配置文件,執(zhí)行SQL修改表結(jié)構(gòu)、約束和主鍵等等,涉及到跨多個(gè)版本的數(shù)據(jù)庫升級(jí)就變得繁瑣并且麻煩了

3.創(chuàng)建臨時(shí)表,把舊的數(shù)據(jù)拷貝到臨時(shí)表,然后刪除舊的數(shù)據(jù)表并且把臨時(shí)表設(shè)置為數(shù)據(jù)表。

優(yōu)點(diǎn):能夠保留數(shù)據(jù),支持表結(jié)構(gòu)的修改,約束、主鍵的變更,實(shí)現(xiàn)起來比較簡(jiǎn)單
缺點(diǎn):實(shí)現(xiàn)的步驟比較多

綜合考慮,第三種方法是一個(gè)比較靠譜的方案。

主要步驟

根據(jù)這個(gè)思路,分析了一下數(shù)據(jù)庫升級(jí)了主要步驟大概如下:

  • 獲取數(shù)據(jù)庫中舊的表
  • 修改表名,添加后綴“_bak”,把舊的表當(dāng)做備份表
  • 創(chuàng)建新的表
  • 獲取新創(chuàng)建的表
  • 遍歷舊的表和新表,對(duì)比取出需要遷移的表的字段
  • 數(shù)據(jù)遷移處理
  • 刪除備份表

使用到的SQL語句分析

這些操作都是和數(shù)據(jù)庫操作有關(guān)系的,所以問題的關(guān)鍵是對(duì)應(yīng)步驟的SQL語句了,下面分析下用到的主要的SQL語句:

獲取數(shù)據(jù)庫中舊的表

SELECT * from sqlite_master WHERE type='table'

結(jié)果如下,可以看到有type | name | tbl_name | rootpage | sql 這些數(shù)據(jù)庫字段,我們只要用到name也就是數(shù)據(jù)庫名稱這個(gè)字段就行了

sqlite> SELECT * from sqlite_master WHERE type='table'
 ...> ;
+-------+---------------+---------------+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| type | name   | tbl_name  | rootpage | sql                                                     |
+-------+---------------+---------------+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| table | t_message_bak | t_message_bak | 2  | CREATE TABLE "t_message_bak" (messageID TEXT, messageType INTEGER, messageJsonContent TEXT, retriveTimeString INTEGER, postTimeString INTEGER, readState INTEGER, PRIMARY KEY(messageID))        |
| table | t_message  | t_message  | 4  | CREATE TABLE t_message (
 messageID TEXT, 
 messageType INTEGER,
 messageJsonContent TEXT, 
 retriveTimeString INTEGER, 
 postTimeString INTEGER, 
 readState INTEGER, 
 addColumn INTEGER,
 PRIMARY KEY(messageID)
) |
+-------+---------------+---------------+----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 行于數(shù)據(jù)集 (0.03 秒)

修改表名,添加后綴“_bak”,把舊的表當(dāng)做備份表

-- 把t_message表修改為t_message_bak表 
ALTER TABLE t_message RENAME TO t_message_bak

獲取表字段信息

-- 獲取t_message_bak表的字段信息
PRAGMA table_info('t_message_bak')

獲取到的表字段信息如下,可以看到有| cid | name | type | notnull | dflt_value | pk | 這些數(shù)據(jù)庫字段,我們只要用到name也就是字段名稱這個(gè)字段就行了

sqlite> PRAGMA table_info('t_message_bak');
+------+--------------------+---------+---------+------------+------+
| cid | name    | type | notnull | dflt_value | pk |
+------+--------------------+---------+---------+------------+------+
| 0 | messageID   | TEXT | 0  | NULL  | 1 |
| 1 | messageType  | INTEGER | 0  | NULL  | 0 |
| 2 | messageJsonContent | TEXT | 0  | NULL  | 0 |
| 3 | retriveTimeString | INTEGER | 0  | NULL  | 0 |
| 4 | postTimeString  | INTEGER | 0  | NULL  | 0 |
| 5 | readState   | INTEGER | 0  | NULL  | 0 |
+------+--------------------+---------+---------+------------+------+
6 行于數(shù)據(jù)集 (0.01 秒)

使用子查詢進(jìn)行數(shù)據(jù)遷移處理

INSERT INTO t_message(messageID, messageType, messageJsonContent, retriveTimeString,
 postTimeString, readState) SELECT messageID, messageType, messageJsonContent, retriveTimeString,
 postTimeString, readState FROM t_message_bak

把t_message_bak表中的messageID, messageType, messageJsonContent, retriveTimeString, postTimeString, readState這些字段的值復(fù)制到t_message表中

代碼實(shí)現(xiàn)

接下來就到了代碼的實(shí)現(xiàn)步驟了

// 創(chuàng)建新的臨時(shí)表,把數(shù)據(jù)導(dǎo)入臨時(shí)表,然后用臨時(shí)表替換原表
- (void)baseDBVersionControl {
 NSString * version_old = ValueOrEmpty(MMUserDefault.dbVersion);
 NSString * version_new = [NSString stringWithFormat:@"%@", DB_Version];
 NSLog(@"dbVersionControl before: %@ after: %@",version_old,version_new);

 // 數(shù)據(jù)庫版本升級(jí)
 if (version_old != nil  ![version_new isEqualToString:version_old]) {

  // 獲取數(shù)據(jù)庫中舊的表
  NSArray* existsTables = [self sqliteExistsTables];
  NSMutableArray* tmpExistsTables = [NSMutableArray array];

  // 修改表名,添加后綴“_bak”,把舊的表當(dāng)做備份表
  for (NSString* tablename in existsTables) {
   [tmpExistsTables addObject:[NSString stringWithFormat:@"%@_bak", tablename]];
   [self.databaseQueue inDatabase:^(FMDatabase *db) {
    NSString* sql = [NSString stringWithFormat:@"ALTER TABLE %@ RENAME TO %@_bak", tablename, tablename];
    [db executeUpdate:sql];
   }];
  }
  existsTables = tmpExistsTables;

  // 創(chuàng)建新的表
  [self initTables];

  // 獲取新創(chuàng)建的表
  NSArray* newAddedTables = [self sqliteNewAddedTables];

  // 遍歷舊的表和新表,對(duì)比取出需要遷移的表的字段
  NSDictionary* migrationInfos = [self generateMigrationInfosWithOldTables:existsTables newTables:newAddedTables];

  // 數(shù)據(jù)遷移處理
  [migrationInfos enumerateKeysAndObjectsUsingBlock:^(NSString* newTableName, NSArray* publicColumns, BOOL * _Nonnull stop) {
   NSMutableString* colunmsString = [NSMutableString new];
   for (int i = 0; ipublicColumns.count; i++) {
    [colunmsString appendString:publicColumns[i]];
    if (i != publicColumns.count-1) {
     [colunmsString appendString:@", "];
    }
   }
   NSMutableString* sql = [NSMutableString new];
   [sql appendString:@"INSERT INTO "];
   [sql appendString:newTableName];
   [sql appendString:@"("];
   [sql appendString:colunmsString];
   [sql appendString:@")"];
   [sql appendString:@" SELECT "];
   [sql appendString:colunmsString];
   [sql appendString:@" FROM "];
   [sql appendFormat:@"%@_bak", newTableName];

   [self.databaseQueue inDatabase:^(FMDatabase *db) {
    [db executeUpdate:sql];
   }];
  }];

  // 刪除備份表
  [self.databaseQueue inDatabase:^(FMDatabase *db) {
   [db beginTransaction];
   for (NSString* oldTableName in existsTables) {
    NSString* sql = [NSString stringWithFormat:@"DROP TABLE IF EXISTS %@", oldTableName];
    [db executeUpdate:sql];
   }
   [db commit];
  }];

  MMUserDefault.dbVersion = version_new;

 } else {
  MMUserDefault.dbVersion = version_new;
 }
}

- (NSDictionary*)generateMigrationInfosWithOldTables:(NSArray*)oldTables newTables:(NSArray*)newTables {
 NSMutableDictionaryNSString*, NSArray* >* migrationInfos = [NSMutableDictionary dictionary];
 for (NSString* newTableName in newTables) {
  NSString* oldTableName = [NSString stringWithFormat:@"%@_bak", newTableName];
  if ([oldTables containsObject:oldTableName]) {
   // 獲取表數(shù)據(jù)庫字段信息
   NSArray* oldTableColumns = [self sqliteTableColumnsWithTableName:oldTableName];
   NSArray* newTableColumns = [self sqliteTableColumnsWithTableName:newTableName];
   NSArray* publicColumns = [self publicColumnsWithOldTableColumns:oldTableColumns newTableColumns:newTableColumns];

   if (publicColumns.count > 0) {
    [migrationInfos setObject:publicColumns forKey:newTableName];
   }
  }
 }
 return migrationInfos;
}

- (NSArray*)publicColumnsWithOldTableColumns:(NSArray*)oldTableColumns newTableColumns:(NSArray*)newTableColumns {
 NSMutableArray* publicColumns = [NSMutableArray array];
 for (NSString* oldTableColumn in oldTableColumns) {
  if ([newTableColumns containsObject:oldTableColumn]) {
   [publicColumns addObject:oldTableColumn];
  }
 }
 return publicColumns;
}

- (NSArray*)sqliteTableColumnsWithTableName:(NSString*)tableName {
 __block NSMutableArrayNSString*>* tableColumes = [NSMutableArray array];
 [self.databaseQueue inDatabase:^(FMDatabase *db) {
  NSString* sql = [NSString stringWithFormat:@"PRAGMA table_info('%@')", tableName];
  FMResultSet *rs = [db executeQuery:sql];
  while ([rs next]) {
   NSString* columnName = [rs stringForColumn:@"name"];
   [tableColumes addObject:columnName];
  }
 }];
 return tableColumes;
}

- (NSArray*)sqliteExistsTables {
 __block NSMutableArrayNSString*>* existsTables = [NSMutableArray array];
 [self.databaseQueue inDatabase:^(FMDatabase *db) {
  NSString* sql = @"SELECT * from sqlite_master WHERE type='table'";
  FMResultSet *rs = [db executeQuery:sql];
  while ([rs next]) {
   NSString* tablename = [rs stringForColumn:@"name"];
   [existsTables addObject:tablename];
  }
 }];
 return existsTables;
}

- (NSArray*)sqliteNewAddedTables {
 __block NSMutableArrayNSString*>* newAddedTables = [NSMutableArray array];
 [self.databaseQueue inDatabase:^(FMDatabase *db) {
  NSString* sql = @"SELECT * from sqlite_master WHERE type='table' AND name NOT LIKE '%_bak'";
  FMResultSet *rs = [db executeQuery:sql];
  while ([rs next]) {
   NSString* tablename = [rs stringForColumn:@"name"];
   [newAddedTables addObject:tablename];
  }
 }];
 return newAddedTables;
}

問題

sqlite 刪除表文件的大小不變的問題

如有疑問請(qǐng)留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!

您可能感興趣的文章:
  • VUE中使用HTTP庫Axios方法詳解
  • iOS系統(tǒng)的底層通知框架庫示例詳解
  • 淺談強(qiáng)大易用支持URL Rewrite的iOS路由庫FFRouter
  • iOS開發(fā)筆記之鍵盤、靜態(tài)庫、動(dòng)畫和Crash定位
  • 基于iOS Realm數(shù)據(jù)庫的使用實(shí)例詳解
  • iOS開發(fā)中如何優(yōu)雅的調(diào)試數(shù)據(jù)庫詳解
  • iOS中.a和.framework靜態(tài)庫的創(chuàng)建與.bundle資源包的使用詳解
  • IOS UIImagePickerController從拍照、圖庫、相冊(cè)獲取圖片
  • iOS中FMDB數(shù)據(jù)庫之增刪改查使用實(shí)例
  • ios動(dòng)態(tài)庫和靜態(tài)庫的區(qū)別

標(biāo)簽:汕頭 宿州 三明 咸寧 內(nèi)江 林芝 朔州 AXB

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《IOS 數(shù)據(jù)庫升級(jí)數(shù)據(jù)遷移的實(shí)例詳解》,本文關(guān)鍵詞  IOS,數(shù)據(jù)庫,升級(jí),數(shù)據(jù),遷移,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《IOS 數(shù)據(jù)庫升級(jí)數(shù)據(jù)遷移的實(shí)例詳解》相關(guān)的同類信息!
  • 本頁收集關(guān)于IOS 數(shù)據(jù)庫升級(jí)數(shù)據(jù)遷移的實(shí)例詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    91麻豆爱豆果冻天美星空| 久久国产一久久高清| 日韩免费片| 精品久久久久久中文字幕一区 | 99热精品在线| 欧美日本二区| 久久99这里只有精品国产| 色综合久久天天综合绕观看| 天堂网中文字幕| 精品久久久久久综合网| 99久久精品国产高清一区二区| 精品久久久久久免费影院| 久久国产影视免费精品| 久久福利影视| 国产a网| 国产伦久视频免费观看视频| 日本在线不卡视频| 国产网站免费| 91麻豆精品国产片在线观看| 欧美日本免费| 国产91精品一区二区| 天天做人人爱夜夜爽2020毛片| 日韩av成人| 二级片在线观看| 日本伦理片网站| 一级毛片视频免费| 欧美日本二区| 二级片在线观看| 精品国产亚洲一区二区三区| 日韩免费片| 国产美女在线一区二区三区| 精品国产亚一区二区三区| 国产伦久视频免费观看 视频| 99色视频在线| 国产激情视频在线观看| 久久福利影视| 久久成人亚洲| 国产不卡在线观看视频| 国产激情视频在线观看| 99久久精品国产麻豆| 韩国三级香港三级日本三级| 四虎论坛| 美女被草网站| 高清一级毛片一本到免费观看| 亚洲第一色在线| 国产不卡在线观看视频| 日本免费乱理伦片在线观看2018| 免费一级生活片| 日本特黄特色aa大片免费| 一级毛片视频免费| 成人影院一区二区三区| 国产视频久久久久| 日日夜人人澡人人澡人人看免| 欧美日本免费| 精品国产一区二区三区久久久蜜臀| 久久精品免视看国产成人2021| 国产一区二区精品| 欧美激情影院| 日日日夜夜操| 99久久精品国产麻豆| 国产伦久视频免费观看视频| 色综合久久天天综合绕观看| 青青青草影院 | 高清一级毛片一本到免费观看| 日本伦理片网站| 亚洲 激情| 国产a网| 四虎精品在线观看| 日韩av片免费播放| 国产伦久视频免费观看 视频| 免费毛片基地| 黄色免费三级| 亚飞与亚基在线观看| 精品在线视频播放| 国产一区二区精品久久91| 成人免费观看的视频黄页| 日本在线不卡视频| 美女免费毛片| 国产伦久视频免费观看 视频| 色综合久久天天综合绕观看| 韩国毛片免费大片| 青青青草视频在线观看| 久久精品大片| 国产成人精品综合久久久| 亚洲精品中文字幕久久久久久| 美女被草网站| 日韩专区在线播放| 精品久久久久久中文字幕一区 | 精品国产一区二区三区精东影业| 日韩一级黄色片| 黄视频网站免费看| 日本久久久久久久 97久久精品一区二区三区 狠狠色噜噜狠狠狠狠97 日日干综合 五月天婷婷在线观看高清 九色福利视频 | 一级女人毛片人一女人| 久久久久久久久综合影视网| 亚洲www美色| 麻豆系列国产剧在线观看| 久久国产一久久高清| 国产一区二区高清视频| 黄视频网站免费| 精品在线视频播放| 欧美爱色| 毛片高清| 日本久久久久久久 97久久精品一区二区三区 狠狠色噜噜狠狠狠狠97 日日干综合 五月天婷婷在线观看高清 九色福利视频 | 999久久66久6只有精品| 欧美激情影院| 国产网站免费在线观看| 久久国产精品自线拍免费| 黄色福利| 天堂网中文字幕| 一级毛片视频免费| 999精品视频在线| 日韩专区第一页| 毛片成人永久免费视频| 青青久久精品| 日韩免费在线视频| 国产精品自拍在线观看| 二级片在线观看| 日韩中文字幕一区二区不卡| 美女被草网站| 毛片成人永久免费视频| 国产国产人免费视频成69堂| 欧美大片一区| 黄视频网站在线免费观看| 韩国三级香港三级日本三级| 美女免费精品高清毛片在线视| 精品久久久久久综合网| 久草免费在线观看| 免费一级生活片| 你懂的福利视频| 国产伦精品一区二区三区在线观看| 可以免费看毛片的网站| 高清一级毛片一本到免费观看| 国产高清在线精品一区a| 色综合久久天天综合| 国产高清在线精品一区a| 999久久66久6只有精品| 欧美一级视频免费观看| 欧美电影免费| 999精品视频在线| 青青久久精品| 精品在线视频播放| 成人免费一级纶理片| 久久99这里只有精品国产| 青青青草视频在线观看| 亚洲精品中文字幕久久久久久| 91麻豆精品国产片在线观看| 国产成+人+综合+亚洲不卡| 欧美大片一区| 精品国产一区二区三区精东影业| 欧美爱色| 欧美大片aaaa一级毛片| 二级片在线观看| 美女被草网站| 九九久久99综合一区二区| 九九久久国产精品大片| 香蕉视频三级| 成人a大片在线观看| 国产伦精品一区二区三区在线观看| 四虎精品在线观看| 欧美大片一区| 成人高清视频在线观看| 精品视频在线观看免费| 免费一级生活片| 日韩中文字幕一区二区不卡| 一级毛片视频免费| 你懂的福利视频| 黄色福利| 午夜欧美成人久久久久久| 九九干| 国产伦久视频免费观看 视频| a级黄色毛片免费播放视频| 999久久66久6只有精品| 国产高清在线精品一区a| 久草免费在线观看| 久草免费在线观看| 免费毛片基地| 国产美女在线一区二区三区| 欧美激情一区二区三区视频高清| 欧美18性精品| 九九精品在线| 精品国产香蕉伊思人在线又爽又黄| 久久成人亚洲| 久久精品欧美一区二区| 午夜激情视频在线观看| 精品久久久久久免费影院| 二级片在线观看| 麻豆系列国产剧在线观看| 日韩av片免费播放| 日本特黄特色aa大片免费| 黄色免费三级| 你懂的在线观看视频| 欧美爱色| 日本在线www| 国产视频一区二区在线播放| 人人干人人草| 中文字幕一区二区三区 精品| 久久久久久久网| 久久精品免视看国产成人2021| 999久久久免费精品国产牛牛| 黄视频网站在线免费观看|