Ich verwalte eine Anwendung, die regelmäßig eine SQLite-Datenbank aktualisieren und alte Datenbanken in das neue Schema migrieren muss.
Zum Verfolgen der Datenbankversion verwende ich die von sqlite bereitgestellte integrierte Benutzerversionsvariable (sqlite macht mit dieser Variablen nichts, Sie können sie nach Belieben verwenden). Es beginnt bei 0 und Sie können diese Variable mit den folgenden SQLite-Anweisungen abrufen / festlegen:
> PRAGMA user_version;
> PRAGMA user_version = 1;
Wenn die App gestartet wird, überprüfe ich die aktuelle Benutzerversion, wende alle Änderungen an, die erforderlich sind, um das Schema auf den neuesten Stand zu bringen, und aktualisiere dann die Benutzerversion. Ich verpacke die Updates in eine Transaktion, damit die Änderungen nicht festgeschrieben werden, wenn etwas schief geht.
Zum Vornehmen von Schemaänderungen unterstützt sqlite die Syntax "ALTER TABLE" für bestimmte Vorgänge (Umbenennen der Tabelle oder Hinzufügen einer Spalte). Dies ist eine einfache Möglichkeit, vorhandene Tabellen direkt zu aktualisieren. Die Dokumentation finden Sie hier: http://www.sqlite.org/lang_altertable.html . Zum Löschen von Spalten oder anderen Änderungen, die von der Syntax "ALTER TABLE" nicht unterstützt werden, erstelle ich eine neue Tabelle, migriere das Datum hinein, lösche die alte Tabelle und benenne die neue Tabelle in den ursprünglichen Namen um.
application_id
ein zusätzliches Bit zum Identifizieren des Dateiformats nachfile
Dienstprogramm, nicht für Versionen der Datenbank.Die Antwort von Just Curious ist absolut zutreffend (Sie haben es verstanden!) Und wir verwenden sie, um die Version des Datenbankschemas zu verfolgen, das derzeit in der App enthalten ist.
Um die Migrationen durchzuführen, die auftreten müssen, damit user_version mit der erwarteten Schemaversion der App übereinstimmt, verwenden wir eine switch-Anweisung. Hier ist ein geschnittenes Beispiel dafür, wie dies in unserer App Strip aussieht :
quelle
toVersion
in Ihrem Code verwenden? Wie wird damit umgegangen, wenn Sie sich in Version 0 befinden und danach zwei weitere Versionen verfügbar sind? Dies bedeutet, dass Sie von 0 auf 1 und von 1 auf 2 migrieren müssen. Wie gehen Sie damit um?break
Anweisungen in derswitch
, daher werden auch alle nachfolgenden Migrationen stattfinden.Lassen Sie mich einen Migrationscode mit FMDB und MBProgressHUD teilen.
So lesen und schreiben Sie die Versionsnummer des Schemas (dies ist vermutlich Teil einer Modellklasse, in meinem Fall eine Singleton-Klasse namens Database):
Hier ist eine
[self database]
Methode, mit der die Datenbank träge geöffnet wird:Und hier sind Migrationsmethoden, die vom View Controller aufgerufen werden:
Und hier ist der Root View Controller-Code, der die Migration aufruft und MBProgressHUD verwendet, um eine Fortschrittsanzeige anzuzeigen:
quelle
schema_version
nicht , und Pragma ist normalerweise auch nichts, mit dem sich die Leute befassen.Die beste Lösung IMO ist das Erstellen eines SQLite-Upgrade-Frameworks. Ich hatte das gleiche Problem (in der C # -Welt) und habe mein eigenes solches Framework erstellt. Sie können darüber lesen Sie hier . Es funktioniert perfekt und lässt meine (bisher albtraumhaften) Upgrades mit minimalem Aufwand auf meiner Seite funktionieren.
Obwohl die Bibliothek in C # implementiert ist, sollten die dort vorgestellten Ideen auch in Ihrem Fall gut funktionieren.
quelle
1
. Erstellen Sie einen/migrations
Ordner mit der Liste der SQL-basierten Migrationen, wobei jede Migration ungefähr so aussieht:/migrations/001-categories.sql
/migrations/002-posts.sql
2
. Erstellen Sie eine DB-Tabelle mit der Liste der angewendeten Migrationen. Beispiel:3
. Aktualisieren Sie die Bootstrap-Logik der Anwendung so, dass sie vor dem Start die Liste der Migrationen aus dem/migrations
Ordner abruft und die noch nicht angewendeten Migrationen ausführt.Hier ist ein mit JavaScript implementiertes Beispiel: SQLite Client für Node.js Apps
quelle
Einige Hinweise...
1) Ich empfehle, den gesamten Code für die Migration Ihrer Datenbank in eine NSOperation einzufügen und im Hintergrundthread auszuführen. Sie können eine benutzerdefinierte UIAlertView mit einem Drehfeld anzeigen, während die Datenbank migriert wird.
2) Stellen Sie sicher, dass Sie Ihre Datenbank aus dem Bundle in die Dokumente der App kopieren und von diesem Speicherort aus verwenden. Andernfalls überschreiben Sie bei jedem App-Update einfach die gesamte Datenbank und migrieren dann die neue leere Datenbank.
3) FMDB ist großartig, aber seine executeQuery-Methode kann aus irgendeinem Grund keine PRAGMA-Abfragen durchführen. Sie müssen Ihre eigene Methode schreiben, die sqlite3 direkt verwendet, wenn Sie die Schemaversion mit PRAGMA user_version überprüfen möchten.
4) Diese Codestruktur stellt sicher, dass Ihre Updates in der richtigen Reihenfolge ausgeführt werden und dass alle Updates ausgeführt werden, unabhängig davon, wie lange der Benutzer zwischen den App-Updates liegt. Es könnte weiter überarbeitet werden, aber dies ist eine sehr einfache Sichtweise. Diese Methode kann jedes Mal sicher ausgeführt werden, wenn Ihr Daten-Singleton instanziiert wird, und kostet nur eine winzige Datenbank-Abfrage, die nur einmal pro Sitzung ausgeführt wird, wenn Sie Ihren Daten-Singleton ordnungsgemäß eingerichtet haben.
quelle
Wenn Sie das Datenbankschema und den gesamten Code, der es verwendet, im Gleichschritt ändern, wie dies wahrscheinlich bei eingebetteten und am Telefon befindlichen Apps der Fall ist, ist das Problem tatsächlich gut unter Kontrolle (nichts Vergleichbares zu dem Albtraum, der die Schemamigration in einer Unternehmensdatenbank darstellt das kann Hunderte von Apps bedienen - auch nicht alle unter der Kontrolle des DBA ;-).
quelle
Für .net können Sie lib verwenden:
EntityFrameworkCore.Sqlite.Migrations
Es ist einfach, sodass Sie für jede andere Plattform problemlos das gleiche Verhalten wie in lib implementieren können.
quelle