{"id":55000491,"date":"2025-12-01T00:00:00","date_gmt":"2026-02-05T15:59:10","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=491"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"SQL_ServerDatenbank_von_Access_aus_updaten","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/SQL_ServerDatenbank_von_Access_aus_updaten\/","title":{"rendered":"SQL Server-Datenbank von Access aus updaten"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg08.met.vgwort.de\/na\/c236c65793804408857b50de3485e0f2\" width=\"1\" height=\"1\" alt=\"\"><b>Wenn wir eine Access-Anwendung mit SQL Server-Frontend an einen Kunden ausgeliefert haben, m&uuml;ssen wir sicherstellen, dass Updates problemlos funktionieren. Updates haben hier zwei Seiten: Einerseits kann das Access-Frontend um neue Funktionen erweitert werden, andererseits k&ouml;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&ouml;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&szlig;end wieder ein. Wenn die Anwendung bei mehreren Kunden verwendet wird, ist dies jedoch zu aufwendig. In diesem Fall k&ouml;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.<\/b><\/p>\n<p>Access-Entwickler wissen: Eine Access-Datenbank ist niemals fertig. Kunden haben immer neue Anforderungen, die umgesetzt werden m&uuml;ssen. Wenn die Anforderungen auch die Tabellen der Datenbank betreffen, m&uuml;ssen wir bei einer Aktualisierung des Frontends auch das Backend entsprechend erneuern, zum Beispiel indem wir Tabellen hinzuf&uuml;gen oder vorhandene Tabellen um Felder erweitern.<\/p>\n<p>Bei einer Kombination aus Access-Frontend und -Backend ist es damit bereits getan. Wenn die Backend-Datenbank jedoch eine SQL Server-Datenbank ist, k&ouml;nnen noch weitere &Auml;nderungen hinzukommen: Neue gespeicherte Views, gespeicherte Prozeduren, Trigger oder Funktionen.<\/p>\n<p>In den folgenden Abschnitten stellen wir die Voraussetzungen vor und zeigen auch, wie die Aktualisierung beim Start der neuen Version des Frontends automatisch durchgef&uuml;hrt werden kann, sodass die Anwendung direkt danach wieder in Betrieb genommen werden kann.<\/p>\n<h2>Aktualisierung per SQL<\/h2>\n<p>Die Aktualisierung der Elemente einer Backend-Datenbank geschieht beispielsweise beim Hinzuf&uuml;gen oder &Auml;ndern des Tabellenentwurfs durch entsprechende SQL-Skripte wie <b>CREATE TABLE<\/b>, <b>ALTER TABLE <\/b>oder, wenn Tabellen gel&ouml;scht werden sollen, auch durch <b>DROP TABLE<\/b>. Indizes und andere Elemente erstellen wir ebenfalls mit SQL-Anweisungen.<\/p>\n<p>Bei einer reinen Access-L&ouml;sung mit einem Access-Backend kommt hier der zus&auml;tzliche Aufwand auf uns zu, diese Aufrufe manuell zusammenstellen zu m&uuml;ssen.<\/p>\n<p>Es gibt keinen eingebauten Mechanismus, mit dem wir beispielsweise die Unterschiede zwischen zwei Access-Tabellen erfassen und in ein SQL-Skript gie&szlig;en k&ouml;nnen.<\/p>\n<p>Beim SQL Server haben wir es zumindest beim Erstellen vollst&auml;ndig neuer Elemente etwas leichter, denn die entsprechenden Skripte k&ouml;nnen wir uns im SQL Server Management Studio generieren lassen.<\/p>\n<p>Schwieriger wird es, wenn wir nur ein Feld oder einen Index zu einer Tabelle hinzuf&uuml;gen wollen &#8211; hier m&uuml;ssen wir grunds&auml;tzlich erst einmal selbst das ben&ouml;tigte Skript schreiben.<\/p>\n<p>Allerdings gibt es auch Tools, mit denen man die Unterschiede zwischen zwei Datenbankversionen ermitteln kann.<\/p>\n<p>Eines davon stellen wir im Artikel <b>SQL Server-Datenbanken vergleichen mit VS.Code <\/b>(<b>www.vbentwickler.de\/472<\/b>) vorgestellt &#8211; hier k&ouml;nnen wir zumindest die Unterschiede zwischen zwei Versionen ermitteln und daraus die notwendigen Anweisungen ableiten, zum Beispiel zum Erg&auml;nzen eines Feldes in einer Tabelle.<\/p>\n<h2>Voraussetzungen f&uuml;r den Abgleich<\/h2>\n<p>Wenn wir eine neue Version des Frontends an die Kunden verteilen und damit auch das Backend im SQL Server aktualisieren wollen, ben&ouml;tigen wir einige grundlegende Elemente.<\/p>\n<p>Das erste ist eine Tabelle im Backend, in der wir die aktuelle Version des Backends festhalten. Diese enth&auml;lt lediglich das Feld <b>Version <\/b>mit dem Datentyp <b>integer<\/b>, in dem wir die aktuelle Versionsnummer speichern (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_06\/pic_491_001.png\" alt=\"Versionstabelle im SQL Server\" width=\"549,6265\" height=\"183,9567\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Versionstabelle im SQL Server<\/span><\/b><\/p>\n<p>Au&szlig;erdem ben&ouml;tigen wir noch zwei Tabellen im Access-Frontend, in denen wir die Informationen zum Aktualisieren des Backends speichern.<\/p>\n<p>Die erste hei&szlig;t <b>tblVersionen <\/b>und sieht im Entwurf wie in Bild 2 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_06\/pic_491_002.png\" alt=\"Versionstabelle im Access-Frontend\" width=\"599,6265\" height=\"435,8309\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Versionstabelle im Access-Frontend<\/span><\/b><\/p>\n<p>Hier speichern wir grundlegende Informationen zur jeweiligen Version, zum Beispiel die Versionsnummer, das Datum, an dem die Version erstellt wurde, Bemerkungen, das Ausf&uuml;hrungsdatum des Updates und den Status des Updates.<\/p>\n<p>Die zweite Tabelle hei&szlig;t <b>tblVersionsdetails <\/b>(siehe Bild 3). Sie speichert die einzelnen Schritte, die zum Aktualisieren auf die jeweilige Version notwendig sind.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_06\/pic_491_003.png\" alt=\"Tabelle der Versionsdetails\" width=\"649,627\" height=\"491,3718\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Tabelle der Versionsdetails<\/span><\/b><\/p>\n<p>Hier finden wir zun&auml;chst ein Fremdschl&uuml;sselfeld namens <b>VersionID<\/b>, mit der die Zuordnung zu der Version aus der Tabelle <b>tblVersionen <\/b>hergestellt wird. Das Feld <b>SQL <\/b>enth&auml;lt die auszuf&uuml;hrende Anweisung, zum Beispiel zum Anlegen oder L&ouml;schen einer Tabelle, zum Hinzuf&uuml;gen von Feldern oder Indizes oder auch zum Anlegen von Views, gespeicherten Prozeduren oder Funktionen. Im Feld <b>ReihenfolgeID <\/b>legen wir fest, in welcher Reihenfolge diese Schritte ausgef&uuml;hrt werden sollen.<\/p>\n<p>Die &uuml;brigen Felder dienen der Aufzeichnung der Ergebnisse der Aktualisierung.<\/p>\n<p>Sie nehmen den Zeitpunkt der Aktualisierung, den Status und eine eventuelle Fehlermeldung auf, damit diese beim Fehlschlagen einer Aktualisierung ausgewertet werden k&ouml;nnen.<\/p>\n<p>F&uuml;r die beiden Felder <b>VersionID <\/b>und <b>ReihenfolgeID <\/b>haben wir einen zusammengesetzten, eindeutigen Index erstellt, damit jede <b>ReihenfolgeID <\/b>nur einmal je Version vorkommen kann.<\/p>\n<h2>Benutzeroberfl&auml;che zum Verwalten der Versionsupdates<\/h2>\n<p>Die Daten dieser Tabellen wollen wir in einem Formular samt Unterformular verwalten.<\/p>\n<p>Der Entwurf des Hauptformulars samt Unterformular sieht wie in Bild 4 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_06\/pic_491_004.png\" alt=\"Haupt- und Unterformular zum Verwalten der Versionen und Versionsdetails\" width=\"700\" height=\"317,6922\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Haupt- und Unterformular zum Verwalten der Versionen und Versionsdetails<\/span><\/b><\/p>\n<p>Das Hauptformular ist an die Tabelle <b>tblVersionen <\/b>gebunden und zeigt alle Felder dieser Tabelle an. Das Unterformular verwendet eine Abfrage basierend auf der Tabelle <b>tblVersionsdetails <\/b>als Datensatzquelle, welche die enthaltenen Daten nach dem Feld <b>ReihenfolgeID <\/b>filtert:<\/p>\n<pre>SELECT VersionsdetailID, VersionID, Beschreibung, SQL, ReihenfolgeID, AusgefuehrtAm, Erfolgreich, Fehlermeldung FROM tblVersionsdetails ORDER BY tblVersionsdetails.ReihenfolgeID;<\/pre>\n<p>Damit das Unterformular nur die Datens&auml;tze anzeigt, die zu dem im Hauptformular angezeigten Datensatz geh&ouml;ren, sind die Eigenschaften <b>Verkn&uuml;pfen von <\/b>und <b>Verkn&uuml;pfen nach <\/b>des Unterformular-Steuerelements jeweils mit dem Wert <b>VersionID <\/b>gef&uuml;llt.<\/p>\n<p>Das Unterformular (siehe Bild 5) ist als Endlosformular ausgelegt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_06\/pic_491_005.png\" alt=\"Unterformular zum Verwalten der Versionsdetails\" width=\"700\" height=\"166,5999\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Unterformular zum Verwalten der Versionsdetails<\/span><\/b><\/p>\n<p>Es enth&auml;lt neben den gebundenen Feldern noch zwei Schaltfl&auml;chen, die das &Auml;ndern der Reihenfolge durch Verschieben nach oben oder nach unten erm&ouml;glichen.<\/p>\n<p>Im Hauptformular haben wir f&uuml;r das Unterformular-Steuerelement das Ereignis <b>Beim Hingehen <\/b>definiert. Hier pr&uuml;fen wir, ob das Hauptformular einen vorhandenen oder einen neuen, leeren Datensatz anzeigt.<\/p>\n<p>Falls es sich um einen neuen, leeren Datensatz handelt, soll eine Meldung angezeigt werden, damit zun&auml;chst ein Datensatz im Hauptformular angelegt wird:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>sfmVersionen_Enter()\r\n     <span style=\"color:blue;\">If <\/span>Me.NewRecord<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Bitte lege zuerst eine Version an.\", _\r\n             vbOkOnly + vbExclamation, \"Neue Version fehlt\"\r\n         Me.Version.SetFocus\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Ereignisse im Unterformular<\/h2>\n<p>F&uuml;r das Ereignis <b>Beim Anzeigen <\/b>des Unterformulars haben wir die folgende Ereignisprozedur hinterlegt:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Current()\r\n     Me.TimerInterval = 100\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Diese startet den Timer f&uuml;r 100 Millisekunden, dann wird die folgende Ereignisprozedur ausgel&ouml;st:<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>Form_Timer()\r\n     Me.TimerInterval = 0\r\n     <span style=\"color:blue;\">If <\/span>Me.NewRecord<span style=\"color:blue;\"> Then<\/span>\r\n         Me.ReihenfolgeID.DefaultValue = _\r\n             Nz(DMax(\"ReihenfolgeID\", \"tblVersionsdetails\",  _\r\n             \"VersionID = \" & Me.Parent.VersionID), 1)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Diese setzt <b>TimerInterval <\/b>wieder auf <b>0 <\/b>und pr&uuml;ft, ob der Benutzer gerade einen neuen, leeren Datensatz aktiviert hat.<\/p>\n<p>In diesem Fall wird der Standardwert f&uuml;r das Feld <b>ReihenfolgeID <\/b>dieses Datensatzes auf den bisher h&ouml;chsten vergebenen Reihenfolge-Wert der Datens&auml;tze aus <b>tblVersionsdetails <\/b>f&uuml;r die Version aus dem Hauptformular ermittelt und um eins erh&ouml;ht.<\/p>\n<p>Dies m&uuml;ssen wir verz&ouml;gert machen, weil das Unterformular vor dem Hauptformular geladen wird und im Hauptformular noch kein Datensatz ist, f&uuml;r den wir die aktuell h&ouml;chste vergebene <b>ReihenfolgeID <\/b>ermitteln k&ouml;nnen.<\/p>\n<p>Nach 100 Millisekunden ist dies jedoch in der Regel der Fall.<\/p>\n<h2>Verschieben der Versionsdetails nach oben und unten<\/h2>\n<p>Die Schaltfl&auml;che <b>cmdNachOben <\/b>l&ouml;st die Prozedur aus Listing 1 aus.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdNachOben_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>dao.Database\r\n     <span style=\"color:blue;\">Dim <\/span>lngVersionID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngReihenfolgeZielID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngReihenfolgeAktuellID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngAktuellID<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngZielID<span style=\"color:blue;\"> As Long<\/span>\r\n     \r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     \r\n     lngVersionID = Me.Parent!VersionID\r\n     \r\n     <span style=\"color:blue;\">Call<\/span> ReihenfolgeErneuern(db, lngVersionID)\r\n     lngReihenfolgeAktuellID = Me.ReihenfolgeID\r\n     lngReihenfolgeZielID = Nz(DMax(\"ReihenfolgeID\", \"tblVersionsdetails\", \"VersionID = \" & lngVersionID _\r\n         & \" AND ReihenfolgeID &lt; \" & Me!ReihenfolgeID), 0)\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> lngReihenfolgeZielID = 0<span style=\"color:blue;\"> Then<\/span>\r\n         lngZielID = DLookup(\"VersionsdetailID\", \"tblVersionsdetails\", \"VersionID = \" & lngVersionID _\r\n             & \" AND ReihenfolgeID = \" & lngReihenfolgeZielID)\r\n         lngAktuellID = Me!VersionsdetailID\r\n     \r\n         <span style=\"color:blue;\">Call<\/span> ReihenfolgeVertauschen(db, lngVersionID, lngAktuellID, lngZielID, lngReihenfolgeAktuellID, _\r\n             lngReihenfolgeZielID)\r\n     \r\n         Me.Requery\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Kann nicht nach oben verschoben werden.\", vbOKOnly + vbExclamation, \"Kein Verschieben m&ouml;glich\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Verschieben des aktuellen Versionsdetails nach oben<\/span><\/b><\/p>\n<p>Sie holt einen Verweis auf das aktuelle <b>Database<\/b>-Objekt und liest die Version aus dem Hauptformular ein. Dann ruft sie eine Prozedur namens <b>ReihenfolgeErneuern <\/b>auf, die eventuelle Leerstellen in den Werten f&uuml;r die Reihenfolge auff&uuml;llt.<\/p>\n<p>Danach liest sie den Wert des Feldes <b>ReihenfolgeID <\/b>f&uuml;r den aktuellen und zu verschiebenden Datensatz in die Variable <b>lngReihenfolgeAktuellID <\/b>ein. Au&szlig;erdem ermittelt sie mit der <b>DMax<\/b>-Funktion den Wert des Feldes <b>ReihenfolgeID <\/b>f&uuml;r den &uuml;ber dem aktuellen Datensatz liegenden Eintrag.<\/p>\n<p>Dieser Wert kann <b>0 <\/b>sein, wenn wir die Schaltfl&auml;che f&uuml;r den obersten Eintrag anklicken. In diesem Fall erscheint eine entsprechende Meldung. Anderenfalls ermittelt die Funktion den Wert des Feldes <b>VersionsdetailID <\/b>f&uuml;r den zu verschiebenden und f&uuml;r den Zieldatensatz.<\/p>\n<p>Alle ermittelten Informationen werden an die Prozedur ReihenfolgeVertauschen &uuml;bergeben, die den eigentlichen Austausch durchf&uuml;hrt. Schlie&szlig;lich wird das Formular aktualisiert.<\/p>\n<p>Die Prozedur, die durch die Schaltfl&auml;che <b>cmdNachUnten <\/b>ausgel&ouml;st wird, funktioniert &auml;hnlich, ermittelt aber als Ziel den unter dem aktuellen Datensatz befindlichen Datensatz.<\/p>\n<h2>Erneuern der Reihenfolge<\/h2>\n<p>Sollten zwischenzeitlich Datens&auml;tze aus der Tabelle <b>tblVersionsdetails <\/b>gel&ouml;scht worden sein, wollen wir diese auff&uuml;llen k&ouml;nnen beziehungsweise die Werte des Feldes wieder so f&uuml;llen, dass keine L&uuml;cken mehr vorhanden sind.<\/p>\n<p>Dies erledigen wir mit der Prozedur <b>ReihenfolgeErneuern <\/b>aus Listing 2. Die Prozedur nimmt die <b>VersionID <\/b>f&uuml;r zu aktualisierende Version entgegen und durchl&auml;uft alle Datens&auml;tze der Tabelle <b>tblVersionsdetails<\/b>, die zu dieser Version geh&ouml;ren.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>ReihenfolgeErneuern(db<span style=\"color:blue;\"> As <\/span>dao.Database, lngVersionID<span style=\"color:blue;\"> As Long<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>dao.Recordset\r\n     <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblVersionsdetails WHERE VersionID = \" & lngVersionID _\r\n         & \" ORDER BY ReihenfolgeID\", dbOpenDynaset)\r\n     <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n         rst.Edit\r\n         rst!ReihenfolgeID = rst.AbsolutePosition + 1\r\n         rst.Update\r\n         rst.Move<span style=\"color:blue;\">Next<\/span>\r\n     <span style=\"color:blue;\">Loop<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Erneuern der Reihenfolge<\/span><\/b><\/p>\n<p>Dabei wird der Wert des Feldes <b>ReihenfolgeID <\/b>jeweils auf den Wert der Eigenschaft <b>AbsolutePosition <\/b>des aktuellen Datensatzes plus eins eingestellt.<\/p>\n<h2>Vertauschen der Reihenfolge<\/h2>\n<p>Die Prozedur <b>ReihenfolgeVertauschen <\/b>f&uuml;hrt drei Aktionsabfragen durch (siehe Listing 3).<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>ReihenfolgeVertauschen(db<span style=\"color:blue;\"> As <\/span>dao.Database, lngVersionID, lngAktuellID<span style=\"color:blue;\"> As Long<\/span>, lngZielID<span style=\"color:blue;\"> As Long<\/span>, _\r\n         lngReihenfolgeAktuellID<span style=\"color:blue;\"> As Long<\/span>, lngReihenfolgeZielID<span style=\"color:blue;\"> As Long<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     strSQL = \"UPDATE tblVersionsdetails SET ReihenfolgeID = NULL WHERE VersionID = \" & lngVersionID _\r\n         & \" AND VersionsdetailID = \" & lngZielID\r\n     db.Execute strSQL, dbFailOnError\r\n     strSQL = \"UPDATE tblVersionsdetails SET ReihenfolgeID = \" & lngReihenfolgeZielID & \" WHERE VersionID = \" _\r\n         & lngVersionID & \" AND VersionsdetailID = \" & lngAktuellID\r\n     db.Execute strSQL, dbFailOnError\r\n     strSQL = \"UPDATE tblVersionsdetails SET ReihenfolgeID = \" & lngReihenfolgeAktuellID & \" WHERE VersionID = \" _\r\n         & lngVersionID & \" AND VersionsdetailID = \" & lngZielID\r\n     db.Execute strSQL, dbFailOnError\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Vertauschen der Reihenfolge<\/span><\/b><\/p>\n<p>Die erste &auml;ndert den Wert des Feldes <b>ReihenfolgeID <\/b>f&uuml;r den Zieldatensatz auf den Wert <b>NULL<\/b>. Dann wird der Wert des Feldes <b>ReihenfolgeID <\/b>f&uuml;r den zu verschiebenden Datensatz auf den entsprechenden Wert des Zieldatensatzes eingestellt. Schlie&szlig;lich &auml;ndern wir den Wert von <b>ReihenfolgeID <\/b>f&uuml;r den Zieldatensatz auf den Wert des entsprechenden Feldes des zu verschiebenden Datensatzes.<\/p>\n<p>Wir m&uuml;ssen diesen zwischenzeitlich auf NULL &auml;ndern, da wir &uuml;ber die Tabellendefinition keine doppelten Kombinationen aus den Werten f&uuml;r die Felder <b>VersionID <\/b>und <b>ReihenfolgeID <\/b>zulassen.<\/p>\n<h2>Eingabe der Versionsdaten<\/h2>\n<p>In der Formularansicht sieht das Formular nun wie in Bild 6 aus. Im Hauptformular wird die Version angezeigt, im Unterformular die einzelnen Schritte. Wichtig ist, dass wir funktionierende und getestete SQL-Anweisungen f&uuml;r die einzelnen Schritte eingeben. Nach der Eingabe k&ouml;nnen wir dann bereits die automatische Aktualisierung des Backends programmieren.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_06\/pic_491_006.png\" alt=\"Eingabe der Versionsdaten\" width=\"700\" height=\"354,0384\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Eingabe der Versionsdaten<\/span><\/b><\/p>\n<h2>Backend automatisch aktualisieren<\/h2>\n<p>Dazu legen wir eine Prozedur namens <b>VersionAktualisieren <\/b>an, deren ersten Teil wir in Listing 4 sehen. Wir wollen die &Auml;nderungen am Backend &uuml;ber die ADODB-<b>Execute<\/b>-Methode &uuml;bertragen, weshalb wir zuvor noch einen Verweis auf die ADODB-Bibliothek ben&ouml;tigen.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>VersionAktualisieren()\r\n     <span style=\"color:blue;\">Dim <\/span>db<span style=\"color:blue;\"> As <\/span>DAO.Database\r\n     <span style=\"color:blue;\">Dim <\/span>rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>rstDetails<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>strVerbindungszeichenfolge<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngVersionSQLServer<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strResponse<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection\r\n     <span style=\"color:blue;\">Dim <\/span>rstADODB<span style=\"color:blue;\"> As <\/span>ADODB.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>bolVersionErfolgreich<span style=\"color:blue;\"> As Boolean<\/span>\r\n     \r\n     strVerbindungszeichenfolge = \"Provider=MSOLEDBSQL;Data Source=amvDesktop2023;Initial Catalog=DemoDB_V1;\" _\r\n         & \"Integrated Security=SSPI;\"\r\n     <span style=\"color:blue;\">Set<\/span> cnn = <span style=\"color:blue;\">New<\/span> ADODB.Connection\r\n     <span style=\"color:blue;\">Set<\/span> rstADODB = <span style=\"color:blue;\">New<\/span> ADODB.Recordset\r\n     <span style=\"color:blue;\">With<\/span> cnn\r\n         .ConnectionString = strVerbindungszeichenfolge\r\n         .Open\r\n         <span style=\"color:blue;\">Set<\/span> rstADODB.ActiveConnection = cnn\r\n         rstADODB.Open \"SELECT Version FROM tblVersion\", strVerbindungszeichenfolge\r\n         lngVersionSQLServer = rstADODB!Version\r\n                 \r\n         <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n         <span style=\"color:blue;\">Set<\/span> rst = db.OpenRecordset(\"SELECT * FROM tblVersionen WHERE Version &gt; \" & lngVersionSQLServer _\r\n             & \" ORDER BY Version ASC\", dbOpenDynaset)\r\n         ...<\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Aktualisieren des Backends (Teil 1)<\/span><\/b><\/p>\n<p>In der Prozedur stellen wir als Erstes die Verbindungszeichenfolge f&uuml;r die ADODB-Connection zusammen. In dieser musst Du zumindest die Parameter <b>Data Source <\/b>(SQL Server) und <b>Initial Catalog <\/b>(Datenbank), gegebenenfalls aber auch noch die Zugriffsdaten bei Verwendung der SQL Server-Authentifizierung, hinzuf&uuml;gen.<\/p>\n<p>Danach deklarieren und erstellen wir neue <b>Connection<\/b>&#8211; und <b>Recordset<\/b>-Objekte. Die Connection &ouml;ffnen wir nach dem Festlegen der Verbindungszeichenfolge mit der <b>Open<\/b>-Methode. Dann legen wir die Connection als <b>ActiveConnection <\/b>des Recordsets fest und &ouml;ffnen eine Abfrage, welche das Feld <b>Version <\/b>der Tabelle <b>tblVersion <\/b>auf dem SQL Server in die Variable <b>lngVersionSQLServer <\/b>einliest.<\/p>\n<p>Nun &ouml;ffnen wir ein DAO-Recordset auf Basis der Tabelle <b>tblVersionen <\/b>und lesen alle Datens&auml;tze ein, deren Wert im Feld <b>Version <\/b>gr&ouml;&szlig;er ist als der aus der Variablen <b>lngVersionSQLServer<\/b>.<\/p>\n<p>Dabei sortieren wir aufsteigend nach dem Feld <b>Version<\/b>. Au&szlig;erdem stellen wir die Variable <b>bolVersionErfolgreich <\/b>auf <b>True <\/b>ein (siehe Listing 5).<\/p>\n<pre>         ...\r\n         bolVersionErfolgreich = <span style=\"color:blue;\">True<\/span>\r\n         <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rst.EOF\r\n             <span style=\"color:blue;\">Call<\/span> VersionInitialisieren(db, rst)\r\n             cnn.BeginTrans\r\n             bolVersionErfolgreich = <span style=\"color:blue;\">True<\/span>\r\n             <span style=\"color:blue;\">Set<\/span> rstDetails = db.OpenRecordset(\"SELECT * FROM tblVersionsdetails WHERE VersionID = \" _\r\n                 & rst!VersionID & \" ORDER BY ReihenfolgeID ASC\", dbOpenDynaset)\r\n             <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstDetails.EOF\r\n                 strSQL = rstDetails!SQL\r\n                 <span style=\"color:blue;\">If <\/span>SQLAusfuehren(cnn, strSQL, strResponse) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                     rstDetails.Edit\r\n                     rstDetails!AusgefuehrtAm = Now\r\n                     rstDetails!Erfolgreich = <span style=\"color:blue;\">True<\/span>\r\n                     rstDetails.Update\r\n                 <span style=\"color:blue;\">Else<\/span>\r\n                     .RollbackTrans\r\n                     bolVersionErfolgreich = <span style=\"color:blue;\">False<\/span>\r\n                     rstDetails.Edit\r\n                     rstDetails!AusgefuehrtAm = Now\r\n                     rstDetails!Erfolgreich = <span style=\"color:blue;\">False<\/span>\r\n                     rstDetails!Fehlermeldung = strResponse\r\n                     rstDetails.Update\r\n                     <span style=\"color:blue;\">Exit Do<\/span>\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n                 rstDetails.Move<span style=\"color:blue;\">Next<\/span>\r\n             <span style=\"color:blue;\">Loop<\/span>            \r\n             <span style=\"color:blue;\">If <\/span>bolVersionErfolgreich = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                 SQLAusfuehren cnn, \"UPDATE tblVersion SET Version = \" & rst!Version, strResponse\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             rst.Edit\r\n             rst!AusgefuehrtAm = Now\r\n             rst!Erfolgreich = bolVersionErfolgreich\r\n             rst.Update\r\n             <span style=\"color:blue;\">If <\/span>bolVersionErfolgreich = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">Exit Do<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             .CommitTrans\r\n             \r\n             rst.Move<span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Loop<\/span>\r\n         <span style=\"color:blue;\">If <\/span>bolVersionErfolgreich = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">MsgBox<\/span> \"Update nicht erfolgreich. Bitte setzen Sie sich mit dem Hersteller in Verbindung.\", _\r\n                 vbOKOnly + <span style=\"color:blue;\">vbCr<\/span>itical, \"Update nicht erfolgreich\"\r\n         End If        \r\n         .Close\r\n     End <span style=\"color:blue;\">With<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> cnn = Nothing    \r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Aktualisieren des Backends (Teil 2)<\/span><\/b><\/p>\n<p>Dieses Recordset durchlaufen wir in einer <b>Do While<\/b>-Schleife. Hier rufen wir zuerst die Prozedur <b>VersionInitialisieren<\/b> auf, um eventuell bereits vorhandene Ergebnisse eines vorherigen Versuchs aus den Tabellen <b>tblVersionen<\/b> und <b>tblVersionsdetails <\/b>zu l&ouml;schen.<\/p>\n<p>Danach starten wir mit <b>BeginTrans <\/b>eine Transaktion f&uuml;r die Connection. Die Idee dahinter ist, die einzelnen Updates aus der Tabelle <b>tblVersionsdetails <\/b>nur abschlie&szlig;end auszuf&uuml;hren, wenn alle Schritte erfolgreich waren.<\/p>\n<p>Hier lesen wir alle Versionsdetails aus der Tabelle <b>tblVersionsdetails <\/b>in das Recordset <b>rstDetails <\/b>ein &#8211; wiederum aufsteigend sortiert, dieses Mal nach dem Feld <b>ReihenfolgeID<\/b>.<\/p>\n<p>Dieses durchlaufen wir in einer weiteren <b>Do While<\/b>-Schleife. Die auszuf&uuml;hrende SQL-Anweisung legen wir in der Variablen <b>strSQL <\/b>ab.<\/p>\n<p>Dann rufen wir die Funktion <b>SQLAusfuehren <\/b>auf und &uuml;bergeben die Connection, den SQL-Ausdruck sowie einen R&uuml;ckgabeparameter namens <b>strResponse<\/b>. Diese Funktion, die wir im Anschluss beschreiben, f&uuml;hrt die SQL-Anweisung aus <b>strSQL <\/b>aus.<\/p>\n<p>Wenn sie das Ergebnis <b>True <\/b>zur&uuml;ckliefert, war die Aktualisierung erfolgreich. Dann k&ouml;nnen wir in der Tabelle <b>tblDetails <\/b>die Felder <b>AusgefuehrtAm <\/b>und <b>Erfolgreich <\/b>auf die entsprechenden Werte einstellen.<\/p>\n<p>Anderenfalls machen wir zun&auml;chst die Transaktion mit <b>RollBackTrans <\/b>r&uuml;ckg&auml;ngig. Au&szlig;erdem setzen wir <b>bolVersionErfolgreich <\/b>auf <b>False <\/b>und tragen die gleichen Werte wie zuvor und zus&auml;tzlich die zur&uuml;ckgelieferte Fehlermeldung in die Tabelle <b>tblVersionsdetails <\/b>ein. Anschlie&szlig;end verlassen wir die Schleife. <\/p>\n<p>Wenn alle Aktionen aus der Tabelle <b>tblVersionsdetails <\/b>f&uuml;r diese Version erfolgreich waren, enth&auml;lt <b>bolVersionErfolgreich <\/b>nun immer noch den Wert <b>True<\/b>.<\/p>\n<p>In diesem k&ouml;nnen wir die Angabe der Version in der Tabelle <b>tblVersion <\/b>in der SQL Server-Datenbank aktualisieren. Zudem tragen wir in der Tabelle <b>tblVersionen <\/b>des Access-Frontends die entsprechenden Werte f&uuml;r die Felder <b>AusgefuehrtAm <\/b>und <b>Erfolgreich <\/b>ein.<\/p>\n<p>Au&szlig;erdem schlie&szlig;en wir die Transaktion mit <b>CommitTrans <\/b>ab, damit die &Auml;nderungen im SQL Server gespeichert werden.<\/p>\n<p>Anderenfalls verlassen wir die <b>Do While<\/b>-Schleife &uuml;ber die Datens&auml;tze der Tabelle <b>tblVersionen <\/b>und geben eine Meldung aus.<\/p>\n<h2>Funktion zum Aktualisieren der Backend-Datenbank<\/h2>\n<p>Die Funktion <b>SQLAusfuehren <\/b>nutzt die <b>Execute<\/b>-Methode des <b>Connection<\/b>-Objekts aus <b>cnn<\/b>, um die jeweilige SQL-Anweisung auszuf&uuml;hren.<\/p>\n<p>Tritt hierbei ein Fehler auf, wird die Fehlermeldung in den R&uuml;ckgabeparameter <b>strResponse <\/b>geschrieben und der Wert <b>False <\/b>als Funktionsergebnis zur&uuml;ckgegeben:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>SQLAusfuehren(cnn<span style=\"color:blue;\"> As <\/span>ADODB.Connection, _\r\n         strSQL<span style=\"color:blue;\"> As String<\/span>, <span style=\"color:blue;\">Optional<\/span> strResponse<span style=\"color:blue;\"> As String<\/span>)  _\r\n        <span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">With<\/span> cnn\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         .Execute strSQL\r\n         Select Case Err.Number\r\n             <span style=\"color:blue;\">Case <\/span>0\r\n                 SQLAusfuehren = <span style=\"color:blue;\">True<\/span>\r\n             <span style=\"color:blue;\">Case Else<\/span>\r\n                 SQLAusfuehren = <span style=\"color:blue;\">False<\/span>\r\n                 strResponse = Err.Description\r\n         <span style=\"color:blue;\">End Select<\/span>\r\n         <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n     End <span style=\"color:blue;\">With<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<h2>Funktion zum Initialisieren der Tabellen tblVersionen und tblVersionsdetails<\/h2>\n<p>Die Prozedur <b>VersionInitialisieren <\/b>wird aufgerufen, bevor wir mit dem Aktualisieren auf eine Version starten.<\/p>\n<p>Es kann sein, dass wir in vorherigen Versuchen bereits Daten in die Felder dieser Tabellen eingetragen haben. Diese werden nun sowohl in der Tabelle <b>tblVersionen <\/b>als auch in <b>tblVersionsdetails <\/b>geleert beziehungsweise auf <b>False<\/b> eingestellt:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>VersionInitialisieren(db<span style=\"color:blue;\"> As <\/span>DAO.Database, _\r\n         rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset)\r\n     <span style=\"color:blue;\">Dim <\/span>lngVersionID<span style=\"color:blue;\"> As Long<\/span>\r\n     lngVersionID = rst!VersionID\r\n     rst.Edit\r\n     rst!AusgefuehrtAm = Null\r\n     rst!Erfolgreich = <span style=\"color:blue;\">False<\/span>\r\n     rst.Update\r\n     db.Execute \"UPDATE tblVersionsdetails \" _\r\n         & \"SET AusgefuehrtAm = NULL, \" _\r\n         & \"Erfolgreich = False, Fehlermeldung = NULL \" _\r\n         & \"WHERE VersionID = \" & lngVersionID, dbFailOnError\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<h2>Ausprobieren der L&ouml;sung<\/h2>\n<p>In der Beispieldatenbank haben wir f&uuml;r die Version mit der Nummer <b>1 <\/b>die folgende Anweisung hinterlegt:<\/p>\n<pre>CREATE TABLE tblKategorien (KategorieID INT IDENTITY(1,1) PRIMARY KEY, Kategoriebezeichnung VARCHAR(255) NOT NULL);<\/pre>\n<p>In der Version mit der Nummer <b>2 <\/b>finden wir diese Anweisungen:<\/p>\n<pre>CREATE VIEW vwTest AS SELECT * FROM tblKategorien\r\nALTER TABLE dbo.tblKategorien\r\nADD Beschreibung VARCHAR(MAX) NULL;<\/pre>\n<p>Wenn wir diese f&uuml;r eine Datenbank, die noch keines dieser Elemente enth&auml;lt, erstmalig mit der Prozedur <b>VersionAktualisieren<\/b> ausf&uuml;hren, verl&auml;uft alles fehlerfrei und wir erhalten die neue Tabelle <b>tblKategorien<\/b>, die neue View <b>vbTest <\/b>und das neue Feld <b>Beschreibung <\/b>in der Tabelle <b>tblKategorien<\/b>.<\/p>\n<p>Au&szlig;erdem wird das Feld <b>Version <\/b>in der Tabelle <b>tblVersion <\/b>der SQL Server-Datenbank auf <b>2 <\/b>eingestellt.<\/p>\n<p>Rufen wir die Prozedur <b>VersionAktualisieren <\/b>nun erneut auf, geschieht nichts. Das liegt daran, dass die neueste Version der Tabelle <b>tblVersionen <\/b>mit der Version in der SQL Server-Tabelle <b>tblVersion <\/b>&uuml;bereinstimmt.<\/p>\n<p>Um Fehler zu provozieren, stellen wir diesen Wert wieder auf <b>0 <\/b>ein.<\/p>\n<p>Rufen wir die Prozedur erneut auf, erhalten wir die Meldung mit dem Hinweis auf einen Fehler.<\/p>\n<p>Wir k&ouml;nnen dann im Formular <b>frmVersionen <\/b>nachschauen, ob ein Fehler protokolliert wurde, und finden hier die folgende Meldung:<\/p>\n<pre>In der Datenbank ist bereits ein Objekt mit dem Namen \"tblKategorien\" vorhanden.<\/pre>\n<p>Auf diese Weise kann der Benutzer im einfachsten Fall einfach die Frontenddatenbank der Anwendung an den Entwickler schicken, damit er diese korrigieren kann.<\/p>\n<h2>Starten der Aktualisierung beim &Ouml;ffnen der Datenbank<\/h2>\n<p>Das Update sollte direkt beim Starten der Anwendung ausgef&uuml;hrt werden, und zwar bevor das Frontend auf Tabellen im Backend zugreift.<\/p>\n<p>Anschlie&szlig;end kann man dann eine Routine durchlaufen lassen, welche die Tabellenverkn&uuml;pfungen aktualisiert.<\/p>\n<p>Der einfachste Weg, die Prozedur gleich beim Start auszuf&uuml;hren, ist der &uuml;ber ein <b>AutoExec<\/b>-Makro. Ein Makro dieses Namens wird beim Start der Access-Datenbank direkt ausgef&uuml;hrt und erm&ouml;glicht, die Prozedur aufzurufen.<\/p>\n<p>Genau genommen kann man mit der Aktion <b>Ausf&uuml;hrenCode <\/b>des <b>AutoExec<\/b>-Makros nur Funktionen ausf&uuml;hren, daher k&ouml;nnen wir entweder die Prozedur in eine Funktion &auml;ndern oder wir schalten eine Funktion dazwischen. In diesem Fall haben wir uns f&uuml;r den ersten Weg entschieden und das Makro wie in Bild 7 erstellt.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_06\/pic_491_007.png\" alt=\"Das AutoExec-Makro\" width=\"499,6267\" height=\"217,4596\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Das AutoExec-Makro<\/span><\/b><\/p>\n<h2>Zusammenfassung und Ausblick<\/h2>\n<p>Dieser Artikel stellt eine L&ouml;sung vor, mit der wir Aktualisieren an einem SQL Server-Backend &uuml;ber das Frontend auf die SQL Server-Datenbank eines Kunden &uuml;bertragen k&ouml;nnen.<\/p>\n<p>Dabei k&ouml;nnen wir alle denkbaren Aktualisierungen und Erweiterungen durchf&uuml;hren:<\/p>\n<ul>\n<li>Hinzuf&uuml;gen von Tabellen, Tabellenfeldern oder Indizes<\/li>\n<li>Entfernen von Tabellen, Tabellenfeldern oder Indizes<\/li>\n<li>Hinzuf&uuml;gen oder Entfernen von Views, gespeicherten Prozeduren oder Funktionen<\/li>\n<\/ul>\n<p>Wir k&ouml;nnen sogar Daten &uuml;ber diesen Automatismus hinzuf&uuml;gen, beispielsweise wenn wir eine neue Tabelle mit Lookup-Daten hinzuf&uuml;gen: Dann k&ouml;nnen wir auch gleich die ben&ouml;tigten Datens&auml;tze eintragen.<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>SQLServerVonAccessAusAktualisieren.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/C8759DB4-9DAD-4609-A5D3-F5F3C08317C9\/vbe_491.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wenn wir eine Access-Anwendung mit SQL Server-Frontend an einen Kunden ausgeliefert haben, m&uuml;ssen wir sicherstellen, dass Updates problemlos funktionieren. Updates haben hier zwei Seiten: Einerseits kann das Access-Frontend um neue Funktionen erweitert werden, andererseits k&ouml;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&ouml;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&szlig;end wieder ein. Wenn die Anwendung bei mehreren Kunden verwendet wird, ist dies jedoch zu aufwendig. In diesem Fall k&ouml;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.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[662025,66062025,44000006],"tags":[],"yst_prominent_words":[],"class_list":["post-55000491","post","type-post","status-publish","format-standard","hentry","category-662025","category-66062025","category-SQL_Server_und_Co"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000491","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000491"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000491\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000491"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000491"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000491"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000491"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}