Cet article présente principalement des informations pertinentes sur des exemples détaillés de mise à niveau de base de données IOS et de migration de données. Voici des exemples pour vous aider à résoudre les problèmes de mise à niveau de base de données et de migration de données. J'espère que cela pourra aider tout le monde. .
Exemple détaillé de migration de données pour la mise à niveau de la base de données IOS
Résumé :
J'ai rencontré la mise à niveau de la version de la base de données il y a longtemps Pour citer le scénario, l'approche à l'époque consistait simplement à supprimer les anciens fichiers de la base de données et à reconstruire la structure de la base de données et des tables. Cette méthode de mise à niveau violente entraînerait la perte des anciennes données. Il semble désormais que ce ne soit pas une solution élégante. Maintenant, c'est la base de données qui est à nouveau utilisée dans le nouveau projet. Je dois reconsidérer ce problème. J'espère résoudre ce problème d'une manière plus élégante. Nous rencontrerons des scénarios similaires à l'avenir. Nous voulons tous faire mieux, n'est-ce pas ? ?
La situation idéale est la suivante : la base de données est mise à niveau et la structure de la table, les clés primaires et les contraintes sont modifiées. Une fois la nouvelle structure de la table établie, les données seront automatiquement récupérées de l'ancienne table, et. les mêmes champs seront mappés et migrés. Dans la plupart des scénarios commerciaux, les mises à niveau de version de base de données impliquent uniquement l'ajout ou la suppression de champs et la modification des contraintes de clé primaire. Par conséquent, la solution à mettre en œuvre ci-dessous est également basée sur les scénarios commerciaux les plus basiques et les plus couramment utilisés. Quant aux plus compliqués, les scénarios peuvent être élargis sur cette base pour répondre à vos propres attentes.
Sélection et finalisation
Après une recherche en ligne, il n'existe pas de solution simple et complète pour la mise à niveau de la base de données et la migration des données, et j'ai trouvé quelques idées
1 Effacer les anciennes données et. reconstruire la table
Avantages : Simple
Inconvénients : Perte de données
2 Modifier la structure de la table en fonction de la table existante
Avantages : Capable de conserver les données
Inconvénients : Les règles sont relativement lourdes. Vous devez créer un fichier de configuration des champs de base de données, puis lire le fichier de configuration, exécuter SQL pour modifier la structure de la table, les contraintes, les clés primaires, etc. implique de s'étendre sur plusieurs versions. La mise à niveau de la base de données devient lourde et fastidieuse
3. Créez une table temporaire, copiez les anciennes données dans la table temporaire, puis supprimez l'ancienne table de données et définissez la table temporaire en tant que données. tableau.
Avantages : il peut conserver les données, prendre en charge la modification de la structure des tables, les changements de contraintes et de clés primaires, et est relativement simple à mettre en œuvre
Inconvénients : il existe de nombreuses étapes à mettre en œuvre
Tout bien considéré, la troisième méthode est une solution plus fiable.
Principales étapes
Selon cette idée, les principales étapes de la mise à niveau de la base de données sont analysées comme suit :
Obtenir le base de données Ancienne table
Modifiez le nom de la table, ajoutez le suffixe "_bak" et utilisez l'ancienne table comme table de sauvegarde
Créez une nouvelle table
Récupérez la table nouvellement créée
Parcourez l'ancienne table et la nouvelle table, comparez et extrayez les champs de la table dont vous avez besoin à migrer
Traitement de migration des données
Supprimer la table de sauvegarde
Analyse des Instructions SQL utilisées
Ces opérations sont liées aux opérations de base de données, la clé du problème est donc l'instruction SQL correspondant à l'étape. Les principales instructions SQL utilisées sont analysées ci-dessous :
Récupérer l'ancienne. table dans la base de données
SELECT * from sqlite_master WHERE type='table'
Les résultats sont les suivants : il existe des champs de base de données tels que type | tbl_name | . Il suffit d'utiliser le nom, qui est le champ du nom de la base de données
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 秒)
Modifiez le nom de la table, ajoutez le suffixe "_bak" et utilisez l'ancien. table comme table de sauvegarde
-- 把t_message表修改为t_message_bak表 ALTER TABLE t_message RENAME TO t_message_bak
Obtenir les informations sur le champ de la table
-- 获取t_message_bak表的字段信息 PRAGMA table_info('t_message_bak')
Les informations sur le champ de table obtenues sont les suivantes, vous pouvez voir que | cid name | notnull | dflt_value | Pour ces champs de base de données, nous devons uniquement utiliser le nom du champ.
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 秒)
Utiliser des sous-requêtes pour le traitement de la migration des données
INSERT INTO t_message(messageID, messageType, messageJsonContent, retriveTimeString, postTimeString, readState) SELECT messageID, messageType, messageJsonContent, retriveTimeString, postTimeString, readState FROM t_message_bak
Copiez les valeurs de messageID, messageType , messageJsonContent, retriveTimeString, postTimeString, readState des champs de la table t_message_bak vers la table t_message
Implémentation du code
L'étape suivante consiste à implémenter le code
// 创建新的临时表,把数据导入临时表,然后用临时表替换原表 - (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* 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 * 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 * 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 * 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; }
Recommandations associées :
Solution du problème de mise à niveau de la version de la base de données du serveur SQL
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!