Je maintiens une application qui a périodiquement besoin de mettre à jour une base de données sqlite et de migrer les anciennes bases de données vers le nouveau schéma et voici ce que je fais:
Pour suivre la version de la base de données, j'utilise la variable de version utilisateur intégrée fournie par sqlite (sqlite ne fait rien avec cette variable, vous êtes libre de l'utiliser comme bon vous semble). Il commence à 0, et vous pouvez obtenir / définir cette variable avec les instructions sqlite suivantes:
> PRAGMA user_version;
> PRAGMA user_version = 1;
Lorsque l'application démarre, je vérifie la version actuelle de l'utilisateur, j'applique les modifications nécessaires pour mettre à jour le schéma, puis je mets à jour la version de l'utilisateur. J'emballe les mises à jour dans une transaction afin qu'en cas de problème, les modifications ne soient pas validées.
Pour apporter des modifications de schéma, sqlite prend en charge la syntaxe "ALTER TABLE" pour certaines opérations (renommer la table ou ajouter une colonne). C'est un moyen simple de mettre à jour les tables existantes sur place. Consultez la documentation ici: http://www.sqlite.org/lang_altertable.html . Pour supprimer des colonnes ou d'autres modifications qui ne sont pas prises en charge par la syntaxe "ALTER TABLE", je crée une nouvelle table, j'y migre la date, je supprime l'ancienne table et je renomme la nouvelle table avec son nom d'origine.
application_id
est un bit supplémentaire pour identifier le format de fichier parfile
utilitaire par exemple, pas pour les versions de base de données.La réponse de Just Curious est sans appel (vous avez compris mon point!), Et c'est ce que nous utilisons pour suivre la version du schéma de base de données actuellement dans l'application.
Pour exécuter les migrations qui doivent se produire pour obtenir la version user_version correspondant à la version de schéma attendue de l'application, nous utilisons une instruction switch. Voici un exemple de ce à quoi cela ressemble dans notre bande d' applications :
la source
toVersion
dans votre code? Comment est-il géré lorsque vous êtes sur la version 0 et qu'il y a deux autres versions après cela. Cela signifie que vous devez migrer de 0 à 1 et de 1 à 2. Comment gérez-vous cela?break
instruction dans leswitch
, donc toutes les migrations ultérieures auront également lieu.Permettez-moi de partager un code de migration avec FMDB et MBProgressHUD.
Voici comment vous lisez et écrivez le numéro de version du schéma (cela fait probablement partie d'une classe de modèle, dans mon cas, c'est une classe singleton appelée Database):
Voici la
[self database]
méthode qui ouvre paresseusement la base de données:Et voici les méthodes de migration appelées à partir du contrôleur de vue:
Et voici le code du contrôleur de vue racine qui appelle la migration, en utilisant MBProgressHUD pour afficher une lunette de progression:
la source
schema_version
pragma n'est normalement pas quelque chose que les gens traitent non plus.La meilleure solution IMO est de construire un framework de mise à niveau SQLite. J'ai eu le même problème (dans le monde C #) et j'ai construit mon propre framework. Vous pouvez en savoir plus ici . Cela fonctionne parfaitement et fait fonctionner mes mises à niveau (auparavant cauchemardesques) avec un minimum d'effort de ma part.
Bien que la bibliothèque soit implémentée en C #, les idées qui y sont présentées devraient également fonctionner correctement dans votre cas.
la source
1
. Créez un/migrations
dossier avec la liste des migrations basées sur SQL, où chaque migration ressemble à ceci:/migrations/001-categories.sql
/migrations/002-posts.sql
2
. Créez une table de base de données contenant la liste des migrations appliquées, par exemple:3
. Mettez à jour la logique d'amorçage de l'application afin qu'avant son démarrage, elle récupère la liste des migrations du/migrations
dossier et exécute les migrations qui n'ont pas encore été appliquées.Voici un exemple implémenté avec JavaScript: Client SQLite pour les applications Node.js
la source
Quelques conseils...
1) Je recommande de mettre tout le code pour migrer votre base de données dans une NSOperation et de l'exécuter dans le thread d'arrière-plan. Vous pouvez afficher un UIAlertView personnalisé avec une double flèche pendant la migration de la base de données.
2) Assurez-vous que vous copiez votre base de données du bundle dans les documents de l'application et que vous l'utilisez à partir de cet emplacement, sinon vous allez simplement écraser toute la base de données avec chaque mise à jour de l'application, puis migrer la nouvelle base de données vide.
3) FMDB est excellent, mais sa méthode executeQuery ne peut pas faire de requêtes PRAGMA pour une raison quelconque. Vous devrez écrire votre propre méthode qui utilise directement sqlite3 si vous souhaitez vérifier la version du schéma à l'aide de PRAGMA user_version.
4) Cette structure de code garantira que vos mises à jour sont exécutées dans l'ordre et que toutes les mises à jour sont exécutées, quel que soit le temps que l'utilisateur passe entre les mises à jour de l'application. Il pourrait être remanié davantage, mais c'est une façon très simple de l'examiner. Cette méthode peut être exécutée en toute sécurité chaque fois que votre singleton de données est instancié et ne coûte qu'une minuscule requête de base de données qui ne se produit qu'une fois par session si vous configurez correctement votre singleton de données.
la source
Si vous modifiez le schéma de la base de données et tout le code qui l'utilise de manière synchronisée, comme c'est probablement le cas dans les applications intégrées et localisées sur le téléphone, le problème est en fait bien sous contrôle (rien de comparable au cauchemar qu'est la migration de schéma sur une base de données d'entreprise qui peuvent servir des centaines d'applications - pas toutes non plus sous le contrôle du DBA ;-).
la source
Pour .net, vous pouvez utiliser lib:
EntityFrameworkCore.Sqlite.Migrations
C'est simple, donc pour toute autre plate-forme, vous pouvez facilement implémenter le même comportement que dans lib.
la source