SQL Server-Datenbank von Access aus updaten

Möchtest Du den gesamten Artikel lesen? Und vielleicht sogar den Artikel im PDF-Format und die Beispieldateien herunterladen? Dann hole Dir den Artikel gleich hier - völlig kostenlos!

Wenn wir eine Access-Anwendung mit SQL Server-Frontend an einen Kunden ausgeliefert haben, müssen wir sicherstellen, dass Updates problemlos funktionieren. Updates haben hier zwei Seiten: Einerseits kann das Access-Frontend um neue Funktionen erweitert werden, andererseits können diese Funktionen eine Anpassung der SQL Server-Datenbank erfordern. Das Aktualisieren der Access-Datenbank erfolgt im einfachsten Fall durch einfaches Ersetzen der .accdb-Datei. Beim Backend wird es ein wenig aufwendiger: Wir können es nicht einfach ersetzen, da die enthaltenen Daten im laufenden Betrieb bearbeitet wurden. Hier gibt es nun zwei Wege: Wir lassen uns ein Backup des Backends zukommen, aktualisieren es und spielen es anschließend wieder ein. Wenn die Anwendung bei mehreren Kunden verwendet wird, ist dies jedoch zu aufwendig. In diesem Fall können wir das Backend aber auch automatisch durch entsprechenden Code in der neuen Version des Frontends aktualisieren lassen. Wie das gelingt, zeigen wir in diesem Artikel.

Access-Entwickler wissen: Eine Access-Datenbank ist niemals fertig. Kunden haben immer neue Anforderungen, die umgesetzt werden müssen. Wenn die Anforderungen auch die Tabellen der Datenbank betreffen, müssen wir bei einer Aktualisierung des Frontends auch das Backend entsprechend erneuern, zum Beispiel indem wir Tabellen hinzufügen oder vorhandene Tabellen um Felder erweitern.

Bei einer Kombination aus Access-Frontend und -Backend ist es damit bereits getan. Wenn die Backend-Datenbank jedoch eine SQL Server-Datenbank ist, können noch weitere Änderungen hinzukommen: Neue gespeicherte Views, gespeicherte Prozeduren, Trigger oder Funktionen.

In den folgenden Abschnitten stellen wir die Voraussetzungen vor und zeigen auch, wie die Aktualisierung beim Start der neuen Version des Frontends automatisch durchgeführt werden kann, sodass die Anwendung direkt danach wieder in Betrieb genommen werden kann.

Aktualisierung per SQL

Die Aktualisierung der Elemente einer Backend-Datenbank geschieht beispielsweise beim Hinzufügen oder Ändern des Tabellenentwurfs durch entsprechende SQL-Skripte wie CREATE TABLE, ALTER TABLE oder, wenn Tabellen gelöscht werden sollen, auch durch DROP TABLE. Indizes und andere Elemente erstellen wir ebenfalls mit SQL-Anweisungen.

Bei einer reinen Access-Lösung mit einem Access-Backend kommt hier der zusätzliche Aufwand auf uns zu, diese Aufrufe manuell zusammenstellen zu müssen.

Es gibt keinen eingebauten Mechanismus, mit dem wir beispielsweise die Unterschiede zwischen zwei Access-Tabellen erfassen und in ein SQL-Skript gießen können.

Beim SQL Server haben wir es zumindest beim Erstellen vollständig neuer Elemente etwas leichter, denn die entsprechenden Skripte können wir uns im SQL Server Management Studio generieren lassen.

Schwieriger wird es, wenn wir nur ein Feld oder einen Index zu einer Tabelle hinzufügen wollen – hier müssen wir grundsätzlich erst einmal selbst das benötigte Skript schreiben.

Allerdings gibt es auch Tools, mit denen man die Unterschiede zwischen zwei Datenbankversionen ermitteln kann.

Eines davon stellen wir im Artikel SQL Server-Datenbanken vergleichen mit VS.Code (www.vbentwickler.de/472) vorgestellt – hier können wir zumindest die Unterschiede zwischen zwei Versionen ermitteln und daraus die notwendigen Anweisungen ableiten, zum Beispiel zum Ergänzen eines Feldes in einer Tabelle.

Voraussetzungen für den Abgleich

Wenn wir eine neue Version des Frontends an die Kunden verteilen und damit auch das Backend im SQL Server aktualisieren wollen, benötigen wir einige grundlegende Elemente.

Das erste ist eine Tabelle im Backend, in der wir die aktuelle Version des Backends festhalten. Diese enthält lediglich das Feld Version mit dem Datentyp integer, in dem wir die aktuelle Versionsnummer speichern (siehe Bild 1).

Versionstabelle im SQL Server

Bild 1: Versionstabelle im SQL Server

Außerdem benötigen wir noch zwei Tabellen im Access-Frontend, in denen wir die Informationen zum Aktualisieren des Backends speichern.

Die erste heißt tblVersionen und sieht im Entwurf wie in Bild 2 aus.

Versionstabelle im Access-Frontend

Bild 2: Versionstabelle im Access-Frontend

Hier speichern wir grundlegende Informationen zur jeweiligen Version, zum Beispiel die Versionsnummer, das Datum, an dem die Version erstellt wurde, Bemerkungen, das Ausführungsdatum des Updates und den Status des Updates.

Die zweite Tabelle heißt tblVersionsdetails (siehe Bild 3). Sie speichert die einzelnen Schritte, die zum Aktualisieren auf die jeweilige Version notwendig sind.

Tabelle der Versionsdetails

Bild 3: Tabelle der Versionsdetails

Hier finden wir zunächst ein Fremdschlüsselfeld namens VersionID, mit der die Zuordnung zu der Version aus der Tabelle tblVersionen hergestellt wird. Das Feld SQL enthält die auszuführende Anweisung, zum Beispiel zum Anlegen oder Löschen einer Tabelle, zum Hinzufügen von Feldern oder Indizes oder auch zum Anlegen von Views, gespeicherten Prozeduren oder Funktionen. Im Feld ReihenfolgeID legen wir fest, in welcher Reihenfolge diese Schritte ausgeführt werden sollen.

Die übrigen Felder dienen der Aufzeichnung der Ergebnisse der Aktualisierung.

Sie nehmen den Zeitpunkt der Aktualisierung, den Status und eine eventuelle Fehlermeldung auf, damit diese beim Fehlschlagen einer Aktualisierung ausgewertet werden können.

Für die beiden Felder VersionID und ReihenfolgeID haben wir einen zusammengesetzten, eindeutigen Index erstellt, damit jede ReihenfolgeID nur einmal je Version vorkommen kann.

Benutzeroberfläche zum Verwalten der Versionsupdates

Die Daten dieser Tabellen wollen wir in einem Formular samt Unterformular verwalten.

Der Entwurf des Hauptformulars samt Unterformular sieht wie in Bild 4 aus.

Haupt- und Unterformular zum Verwalten der Versionen und Versionsdetails

Bild 4: Haupt- und Unterformular zum Verwalten der Versionen und Versionsdetails

Das Hauptformular ist an die Tabelle tblVersionen gebunden und zeigt alle Felder dieser Tabelle an. Das Unterformular verwendet eine Abfrage basierend auf der Tabelle tblVersionsdetails als Datensatzquelle, welche die enthaltenen Daten nach dem Feld ReihenfolgeID filtert:

SELECT VersionsdetailID, VersionID, Beschreibung, SQL, ReihenfolgeID, AusgefuehrtAm, Erfolgreich, Fehlermeldung FROM tblVersionsdetails ORDER BY tblVersionsdetails.ReihenfolgeID;

Damit das Unterformular nur die Datensätze anzeigt, die zu dem im Hauptformular angezeigten Datensatz gehören, sind die Eigenschaften Verknüpfen von und Verknüpfen nach des Unterformular-Steuerelements jeweils mit dem Wert VersionID gefüllt.

Das Unterformular (siehe Bild 5) ist als Endlosformular ausgelegt.

Unterformular zum Verwalten der Versionsdetails

Bild 5: Unterformular zum Verwalten der Versionsdetails

Es enthält neben den gebundenen Feldern noch zwei Schaltflächen, die das Ändern der Reihenfolge durch Verschieben nach oben oder nach unten ermöglichen.

Im Hauptformular haben wir für das Unterformular-Steuerelement das Ereignis Beim Hingehen definiert. Hier prüfen wir, ob das Hauptformular einen vorhandenen oder einen neuen, leeren Datensatz anzeigt.

Falls es sich um einen neuen, leeren Datensatz handelt, soll eine Meldung angezeigt werden, damit zunächst ein Datensatz im Hauptformular angelegt wird:

Private Sub sfmVersionen_Enter()
     If Me.NewRecord Then
         MsgBox "Bitte lege zuerst eine Version an.", _
             vbOkOnly + vbExclamation, "Neue Version fehlt"
         Me.Version.SetFocus
     End If
End Sub

Ereignisse im Unterformular

Für das Ereignis Beim Anzeigen des Unterformulars haben wir die folgende Ereignisprozedur hinterlegt:

Private Sub Form_Current()
     Me.TimerInterval = 100
End Sub

Diese startet den Timer für 100 Millisekunden, dann wird die folgende Ereignisprozedur ausgelöst:

Private Sub Form_Timer()
     Me.TimerInterval = 0
     If Me.NewRecord Then
         Me.ReihenfolgeID.DefaultValue = _
             Nz(DMax("ReihenfolgeID", "tblVersionsdetails",  _
             "VersionID = " & Me.Parent.VersionID), 1)
     End If
End Sub

Diese setzt TimerInterval wieder auf 0 und prüft, ob der Benutzer gerade einen neuen, leeren Datensatz aktiviert hat.

In diesem Fall wird der Standardwert für das Feld ReihenfolgeID dieses Datensatzes auf den bisher höchsten vergebenen Reihenfolge-Wert der Datensätze aus tblVersionsdetails für die Version aus dem Hauptformular ermittelt und um eins erhöht.

Dies müssen wir verzögert machen, weil das Unterformular vor dem Hauptformular geladen wird und im Hauptformular noch kein Datensatz ist, für den wir die aktuell höchste vergebene ReihenfolgeID ermitteln können.

Nach 100 Millisekunden ist dies jedoch in der Regel der Fall.

Verschieben der Versionsdetails nach oben und unten

Die Schaltfläche cmdNachOben löst die Prozedur aus Listing 1 aus.

Private Sub cmdNachOben_Click()
     Dim db As dao.Database
     Dim lngVersionID As Long
     Dim lngReihenfolgeZielID As Long
     Dim lngReihenfolgeAktuellID As Long
     Dim lngAktuellID As Long
     Dim lngZielID As Long
     
     Set db = CurrentDb
     
     lngVersionID = Me.Parent!VersionID
     
     Call ReihenfolgeErneuern(db, lngVersionID)
     lngReihenfolgeAktuellID = Me.ReihenfolgeID
     lngReihenfolgeZielID = Nz(DMax("ReihenfolgeID", "tblVersionsdetails", "VersionID = " & lngVersionID _
         & " AND ReihenfolgeID < " & Me!ReihenfolgeID), 0)
     If Not lngReihenfolgeZielID = 0 Then
         lngZielID = DLookup("VersionsdetailID", "tblVersionsdetails", "VersionID = " & lngVersionID _
             & " AND ReihenfolgeID = " & lngReihenfolgeZielID)
         lngAktuellID = Me!VersionsdetailID
     
         Call ReihenfolgeVertauschen(db, lngVersionID, lngAktuellID, lngZielID, lngReihenfolgeAktuellID, _
             lngReihenfolgeZielID)
     
         Me.Requery
     Else
         MsgBox "Kann nicht nach oben verschoben werden.", vbOKOnly + vbExclamation, "Kein Verschieben möglich"
     End If
End Sub

Listing 1: Verschieben des aktuellen Versionsdetails nach oben

Sie holt einen Verweis auf das aktuelle Database-Objekt und liest die Version aus dem Hauptformular ein. Dann ruft sie eine Prozedur namens ReihenfolgeErneuern auf, die eventuelle Leerstellen in den Werten für die Reihenfolge auffüllt.

Danach liest sie den Wert des Feldes ReihenfolgeID für den aktuellen und zu verschiebenden Datensatz in die Variable lngReihenfolgeAktuellID ein. Außerdem ermittelt sie mit der DMax-Funktion den Wert des Feldes ReihenfolgeID für den über dem aktuellen Datensatz liegenden Eintrag.

Dieser Wert kann 0 sein, wenn wir die Schaltfläche für den obersten Eintrag anklicken. In diesem Fall erscheint eine entsprechende Meldung. Anderenfalls ermittelt die Funktion den Wert des Feldes VersionsdetailID für den zu verschiebenden und für den Zieldatensatz.

Alle ermittelten Informationen werden an die Prozedur ReihenfolgeVertauschen übergeben, die den eigentlichen Austausch durchführt. Schließlich wird das Formular aktualisiert.

Die Prozedur, die durch die Schaltfläche cmdNachUnten ausgelöst wird, funktioniert ähnlich, ermittelt aber als Ziel den unter dem aktuellen Datensatz befindlichen Datensatz.

Erneuern der Reihenfolge

Sollten zwischenzeitlich Datensätze aus der Tabelle tblVersionsdetails gelöscht worden sein, wollen wir diese auffüllen können beziehungsweise die Werte des Feldes wieder so füllen, dass keine Lücken mehr vorhanden sind.

Dies erledigen wir mit der Prozedur ReihenfolgeErneuern aus Listing 2. Die Prozedur nimmt die VersionID für zu aktualisierende Version entgegen und durchläuft alle Datensätze der Tabelle tblVersionsdetails, die zu dieser Version gehören.

Private Sub ReihenfolgeErneuern(db As dao.Database, lngVersionID As Long)
     Dim rst As dao.Recordset
     Set rst = db.OpenRecordset("SELECT * FROM tblVersionsdetails WHERE VersionID = " & lngVersionID _
         & " ORDER BY ReihenfolgeID", dbOpenDynaset)
     Do While Not rst.EOF
         rst.Edit
         rst!ReihenfolgeID = rst.AbsolutePosition + 1
         rst.Update
         rst.MoveNext
     Loop
End Sub

Listing 2: Erneuern der Reihenfolge

Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

den kompletten Artikel im PDF-Format mit Beispieldatenbank

diesen und alle anderen Artikel mit dem Jahresabo

Schreibe einen Kommentar