iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >IOS数据库升级数据迁移的示例分析
  • 471
分享到

IOS数据库升级数据迁移的示例分析

2024-04-02 19:04:59 471人浏览 独家记忆
摘要

这篇文章主要介绍iOS数据库升级数据迁移的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!IOS 数据库升级数据迁移的实例详解概要:很久以前就遇到过数据库版本升级的引用场景,当

这篇文章主要介绍iOS数据库升级数据迁移的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

IOS 数据库升级数据迁移的实例详解

概要:

很久以前就遇到过数据库版本升级的引用场景,当时的做法是简单的删除旧的数据库文件,重建数据库和表结构,这种暴力升级的方式会导致旧的数据的丢失,现在看来这并不不是一个优雅的解决方案,现在一个新的项目中又使用到了数据库,我不得不重新考虑这个问题,我希望用一种比较优雅的方式去解决这个问题,以后我们还会遇到类似的场景,我们都想做的更好不是吗?

理想的情况是:数据库升级,表结构、主键和约束有变化,新的表结构建立之后会自动的从旧的表检索数据,相同的字段进行映射迁移数据,而绝大多数的业务场景下的数据库版本升级是只涉及到字段的增减、修改主键约束,所以下面要实现的方案也是从最基本的、最常用的业务场景去做一个实现,至于更加复杂的场景,可以在此基础上进行扩展,达到符合自己的预期的。

选型定型

网上搜索了下,并没有数据库升级数据迁移简单完整的解决方案,找到了一些思路

1.清除旧的数据,重建表

优点:简单
缺点:数据丢失

2.在已有表的基础上对表结构进行修改

优点:能够保留数据
缺点:规则比较繁琐,要建立一个数据库的字段配置文件,然后读取配置文件,执行sql修改表结构、约束和主键等等,涉及到跨多个版本的数据库升级就变得繁琐并且麻烦了

3.创建临时表,把旧的数据拷贝到临时表,然后删除旧的数据表并且把临时表设置为数据表。

优点:能够保留数据,支持表结构的修改,约束、主键的变更,实现起来比较简单
缺点:实现的步骤比较多

综合考虑,第三种方法是一个比较靠谱的方案。

主要步骤

根据这个思路,分析了一下数据库升级了主要步骤大概如下:

  • 获取数据库中旧的表

  • 修改表名,添加后缀“_bak”,把旧的表当做备份表

  • 创建新的表

  • 获取新创建的表

  • 遍历旧的表和新表,对比取出需要迁移的表的字段

  • 数据迁移处理

  • 删除备份表

使用到的SQL语句分析

这些操作都是和数据库操作有关系的,所以问题的关键是对应步骤的SQL语句了,下面分析下用到的主要的SQL语句:

获取数据库中旧的表

SELECT * from sqlite_master WHERE type='table'

结果如下,可以看到有type | name | tbl_name | rootpage | sql 这些数据库字段,我们只要用到name也就是数据库名称这个字段就行了

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 行于数据集 (0.03 秒)

修改表名,添加后缀“_bak”,把旧的表当做备份表

-- 把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 | 这些数据库字段,我们只要用到name也就是字段名称这个字段就行了

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 行于数据集 (0.01 秒)

使用子查询进行数据迁移处理

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这些字段的值复制到t_message表中

代码实现

接下来就到了代码的实现步骤了

// 创建新的临时表,把数据导入临时表,然后用临时表替换原表
- (void)baseDBVersionControl {
 NSString * version_old = ValueOrEmpty(MMUserDefault.dbVersion);
 NSString * version_new = [NSString stringWithFORMat:@"%@", DB_Version];
 NSLog(@"dbVersionControl before: %@ after: %@",version_old,version_new);

 // 数据库版本升级
 if (version_old != nil && ![version_new isEqualToString:version_old]) {

  // 获取数据库中旧的表
  NSArray* existsTables = [self sqliteExistsTables];
  NSMutableArray* tmpExistsTables = [NSMutableArray array];

  // 修改表名,添加后缀“_bak”,把旧的表当做备份表
  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;

  // 创建新的表
  [self initTables];

  // 获取新创建的表
  NSArray* newAddedTables = [self sqliteNewAddedTables];

  // 遍历旧的表和新表,对比取出需要迁移的表的字段
  NSDictionary* migrationInfos = [self generateMigrationInfosWithOldTables:existsTables newTables:newAddedTables];

  // 数据迁移处理
  [migrationInfos enumerateKeysAndObjectsUsingBlock:^(NSString* newTableName, NSArray* publicColumns, BOOL * _Nonnull stop) {
   NSMutableString* colunmsString = [NSMutableString new];
   for (int i = 0; i<publicColumns.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 {
 NSMutableDictionary<NSString*, NSArray* >* migrationInfos = [NSMutableDictionary dictionary];
 for (NSString* newTableName in newTables) {
  NSString* oldTableName = [NSString stringWithFormat:@"%@_bak", newTableName];
  if ([oldTables containsObject:oldTableName]) {
   // 获取表数据库字段信息
   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 NSMutableArray<NSString*>* 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 NSMutableArray<NSString*>* 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 NSMutableArray<NSString*>* 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;
}

以上是“IOS数据库升级数据迁移的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注编程网数据库频道!

您可能感兴趣的文档:

--结束END--

本文标题: IOS数据库升级数据迁移的示例分析

本文链接: https://www.lsjlt.com/news/57222.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • IOS数据库升级数据迁移的示例分析
    这篇文章主要介绍IOS数据库升级数据迁移的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!IOS 数据库升级数据迁移的实例详解概要:很久以前就遇到过数据库版本升级的引用场景,当...
    99+
    2022-10-18
  • Mysql百万级数据迁移的示例分析
    这篇文章将为大家详细讲解有关Mysql百万级数据迁移的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。     ...
    99+
    2022-10-19
  • oracle数据库迁移到MySQL的示例分析
    这篇文章给大家分享的是有关oracle数据库迁移到MySQL的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。方式一: 手动方式导入导出手动的方式导入, 就是操作步骤会比较...
    99+
    2022-10-18
  • MySQL中数据迁移的示例分析
    这篇文章主要为大家展示了“MySQL中数据迁移的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“MySQL中数据迁移的示例分析”这篇文章吧。1.关于数据迁...
    99+
    2022-10-18
  • DB2 V95 数据库 迁移升级至 V105 实战案例
    cbsdb09-JSJKDB V95迁移升级至tms01db01sz V105步骤 1.       准备工作 新机器tms0...
    99+
    2022-10-18
  • oracle中数据fs到asm迁移的示例分析
    小编给大家分享一下oracle中数据fs到asm迁移的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!(RedHat&nb...
    99+
    2022-10-19
  • WindowsServer 2012数据库迁移分析
    本篇内容主要讲解“WindowsServer 2012数据库迁移分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“WindowsServer 2012数据库迁移...
    99+
    2022-10-18
  • Oracle数据库升级或数据迁移的方法是什么
    本篇文章给大家分享的是有关Oracle数据库升级或数据迁移的方法是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。这里论述了oracle数据库升级的升级前的准备、升级过程和升...
    99+
    2023-06-06
  • 【RMAN】Oracle11g使用rman迁移升级数据库(win_to_linux)
    前言:在迁移Oracle数据库的过程中,我们会遇到很多种情况,例如32位操作系统下的数据库迁移到64位,不同操作系统平台之间的迁移,那么怎么选择迁移工具呢,首先我们需要确认迁移源端和目标端的环境,再次停...
    99+
    2022-10-18
  • mysql5升级mysql8的数据迁移问题
      通过NavicatPremium 可以对数据库进行备份操作。     备份可选择需要备份出来的表结构,视图,函数,以及数据 备份完成,会生成一个备份文件 比如: 20200304162843.nb3 通过备份文件,从Navi...
    99+
    2018-02-03
    mysql5升级mysql8的数据迁移问题
  • 怎么简单分析数据库迁移
    这篇文章给大家介绍怎么简单分析数据库迁移,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。现在NoSQL流行,有一个原因也是因为不需要去刻意处理table的schema,直接存储数据,这样...
    99+
    2022-10-19
  • Oracle数据库部分迁至闪存存储的示例分析
    这篇文章给大家分享的是有关Oracle数据库部分迁至闪存存储的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。环境:Oracle 11.2.0.4 RAC(2 nodes)...
    99+
    2022-10-18
  • MySQL数据库的示例分析
    这篇文章给大家分享的是有关MySQL数据库的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、数据库概要数据库(Database)是存储与管理数据的软件系统,就像一个存入...
    99+
    2022-10-18
  • MySQL数据库千万级数据查询和存储的示例分析
    这篇文章主要介绍MySQL数据库千万级数据查询和存储的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!百万级数据处理方案数据存储结构设计表字段设计表字段 not null,因为 null 值很难查询优化且占用额...
    99+
    2023-06-15
  • Laravel中数据库迁移操作的示例详解
    目录一:创建迁移二:迁移结构1:up方法2:down方法三:运行迁移四:迁移回滚五:回滚后迁移六:可用字段类型七:字段修饰八:修改字段九:删除字段十:索引长度 & Mysql...
    99+
    2023-02-09
    Laravel数据库迁移 Laravel数据库
  • 数据库中sqlnet.ora的示例分析
    小编给大家分享一下数据库中sqlnet.ora的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧! 一、例子1、SQLNET.AUTHENTICATION_SERVICES= (NT...
    99+
    2022-10-19
  • Mysql数据迁徙方法工具的示例分析
    这篇文章给大家分享的是有关Mysql数据迁徙方法工具的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。数据迁徙是每个后端都会遇到的工作之一,本文介绍了一些常见的数据迁徙方法...
    99+
    2022-10-18
  • MySQL数据库中数据约束的示例分析
    这篇文章主要介绍了MySQL数据库中数据约束的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。为了防止不符合规范的数据进入数据库,在用...
    99+
    2022-10-18
  • 数据库版本如何单独升级并将原有数据迁移过去
    本篇文章给大家分享的是有关数据库版本如何单独升级并将原有数据迁移过去,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。在我们开发的应用中,一般都会...
    99+
    2022-10-19
  • 数据库中跨库数据表运算的示例分析
    这篇文章将为大家详细讲解有关数据库中跨库数据表运算的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1. 简单合并(FROM)所谓跨库数据表,是指逻辑上同一张数据表...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作