{"id":55001551,"date":"2025-06-01T00:00:00","date_gmt":"2025-05-07T12:10:48","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1551"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"SQL_ServerTabellenverknuepfungsassistent_Teil_2","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/","title":{"rendered":"SQL Server-Tabellenverkn&uuml;pfungsassistent, Teil 2"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg01.met.vgwort.de\/na\/bf0487477047475db7cbade9e31158b0\" width=\"1\" height=\"1\" alt=\"\"><b>Der SQL Server-Tabellenverkn&uuml;pfungsassistent, den wir im Beitrag &#8222;SQL Server-Tabellenverkn&uuml;pfungsassistent&#8220; (www.access-im-unternehmen.de\/1540) vorgestellt haben, funktioniert in vielen Settings bereits recht gut. Die generelle Praxistauglichkeit zeigt sichjedoch erst, wenn die Anwendung einmal auf andere Benutzer und\/oder Verwendungszwecke st&ouml;&szlig;t. Da dies nun geschehen ist, wollen wir im zweiten Teil der Beitragsreihe zum Thema SQL Server-Tabellenverkn&uuml;pfungsassistent einige &Auml;nderungen und Erweiterungen nachreichen. Dabei geht es im Wesentlichen um die Benennung der Tabellenverkn&uuml;pfungen, die von dem Assistenten entweder initial angelegt oder aktualisiert werden sollen.<\/b><\/p>\n<h2>Probleme beim Einsatz des Tabellenverkn&uuml;pfungsassistenten<\/h2>\n<p>Das Hauptproblem, das uns zur&uuml;ckgemeldet wurde, ist die Inflexibilit&auml;t bei der Verwendung der Bezeichnungen f&uuml;r die Tabellenverkn&uuml;pfungen. Im ersten Teil gingen wir davon aus, dass wir allein mit dem Namen der Tabelle auskommen &#8211; so sah auch das Formular zum Verwalten der zu verkn&uuml;pfenden Tabellen aus (siehe Bild 1).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1551_002.png\" alt=\"Hauptformular Access-Add-Ins\" width=\"424,5589\" height=\"256,2827\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Hauptformular Access-Add-Ins<\/span><\/b><\/p>\n<p>Das Add-In erledigt die folgenden Aufgaben:<\/p>\n<ul>\n<li>Wenn die Access-Anwendung erstmals mit den Tabellen einer SQL Server-Datenbank verkn&uuml;pft werden soll, legt es diese einfach unter dem gleichen Namen an, unter dem diese auch in der SQL Server-Datenbank gespeichert sind &#8211; ohne Ber&uuml;cksichtigung von <b>dbo <\/b>oder anderen Schemabezeichnungen.<\/li>\n<li>Wenn die Tabellenverkn&uuml;pfungen aktualisiert werden sollen, beispielsweise wenn sich der Name der Datenbank oder sich Name\/Adresse des SQL Servers ge&auml;ndert haben, werden auch die Tabellennamen aus dem SQL Server verwendet. Wenn bereits eine Tabelle oder Tabellenverkn&uuml;pfung gleichen Namens vorhanden ist, erscheint eine Inputbox, die dem Benutzer die M&ouml;glichkeit bietet, einen anderen Namen zu w&auml;hlen oder die vorhandene Tabelle oder Tabellenverkn&uuml;pfung zu &uuml;berschreiben.<\/li>\n<\/ul>\n<p>Das initiale Verkn&uuml;pfen ist somit normalerweise immer funktional, au&szlig;er man m&ouml;chte, dass die Tabellenverkn&uuml;pfungen anders benannt werden als die Tabellen auf dem SQL Server.<\/p>\n<p>Das Aktualisieren der Tabellenverkn&uuml;pfungen offenbart allerdings weitere Schwachstellen:<\/p>\n<ul>\n<li>Je nachdem, mit welcher Methode man initial die Tabellenverkn&uuml;pfungen erstellt hat, wird eine Tabellenverkn&uuml;pfung beispielsweise f&uuml;r eine Tabelle wie <b>tblKunden <\/b>auch einmal <b>dbo_tblKunden <\/b>genannt. Damit kommt das Add-In grunds&auml;tzlich nicht zurecht: Es soll die Tabelle <b>tblKunden<\/b> als Tabellenverkn&uuml;pfung angelegt und gepr&uuml;ft werden, ob bereits eine Verkn&uuml;pfung namens <b>tblKunden <\/b>vorhanden ist. Falls nicht, wird die Tabellenverkn&uuml;pfung unter dem Namen <b>tblKunden<\/b> hinzugef&uuml;gt. Das ist nat&uuml;rlich nicht zielf&uuml;hrend, denn dann gibt es zwei Tabellenverkn&uuml;pfungen f&uuml;r die gleiche Tabelle, n&auml;mlich <b>dbo_tblKunden <\/b>und <b>tblKunden<\/b>. Da Abfragen, Formulare, Berichte und VBA in diesem Fall auf die Tabellenverkn&uuml;pfung <b>dbo_tblKunden <\/b>eingestellt sind, greifen diese weiterhin auf die alte Tabellenverkn&uuml;pfung zu, die nicht ge&auml;ndert wurde und gegebenenfalls auf die falsche Datenbank oder den falschen Server verweist.<\/li>\n<li>Eines der Probleme hierbei ist, dass das Add-In die vorhandenen Tabellenverkn&uuml;pfungen nicht den Tabellen der SQL Server-Datenbank zuordnen kann, da es nur den Namen der Tabellenverkn&uuml;pfung mit dem Namen der Tabelle vergleicht.<\/li>\n<li>Au&szlig;erdem pr&uuml;ft das Add-In in der Version aus dem ersten Teil der Beitragsreihe immer nur, ob es bereits eine Tabelle oder Tabellenverkn&uuml;pfung mit dem Namen der anzulegenden Tabellenverkn&uuml;pfung gibt. Das ist eigentlich nur sinnvoll, wenn es bereits Tabellen gleichen Namens gibt, da diese gegebenenfalls nicht &uuml;berschrieben werden sollen. Wenn es eine Verkn&uuml;pfung gleichen Namens gibt, sollte diese eigentlich direkt &uuml;berschrieben werden.<\/li>\n<\/ul>\n<p>Diese Probleme adressieren wir in der &Uuml;berarbeitung des Assistenten im vorliegenden Beitrag.<\/p>\n<h2>Ziele der Anpassung<\/h2>\n<p>Wir wollen also folgende &Auml;nderungen erreichen:<\/p>\n<ul>\n<li>Das Add-In soll zuverl&auml;ssig erkennen, ob eine Tabellenverkn&uuml;pfung sich auf eine in der SQL Server-Datenbank enthaltene Tabelle bezieht und diese dann einfach ersetzen.<\/li>\n<li>Dabei soll dann der Name der Tabellenverkn&uuml;pfung &uuml;bernommen werden, den die zu ersetzende Verkn&uuml;pfung hatte.<\/li>\n<li>Au&szlig;erdem wollen wir dem Benutzer die M&ouml;glichkeit geben, beim initialen Erstellen einer Tabellenverkn&uuml;pfung festzulegen, wie die Tabellenverkn&uuml;pfungen benannt werden sollen. Dazu stehen die beiden Platzhalter <b>Schema<\/b> und <b>Name <\/b>zur Verf&uuml;gung, die man in eckigen Klammern neben weiteren Zeichen angeben kann.<\/li>\n<\/ul>\n<h2>Erster Schritt: Tabelle zum Speichern der Tabelleninformationen<\/h2>\n<p>Da wir nun nicht mehr nur mit den Tabellennamen arbeiten wollen, wie sie im SQL Server vorkommen, sondern auch noch die Namen der vorhandenen Tabellenverkn&uuml;pfungen ber&uuml;cksichtigen wollen, nutzen wir zur &Uuml;bersicht eine Tabelle namens <b>tblTablesTemp<\/b>. Diese ist wie in Bild 2 aufgebaut. Hier speichern wir neben dem Namen der Tabelle im SQL Server auch den Namen der Tabellenverkn&uuml;pfung in der Access-Datenbank. Au&szlig;erdem wollen wir auch noch das Schema (zum Beispiel <b>dbo<\/b>) und den Tabellennamen ohne Schema in eigenen Feldern speichern.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1551_013.png\" alt=\"Tabelle zum Speichern der Tabelleninformationen\" width=\"524,559\" height=\"414,1734\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Tabelle zum Speichern der Tabelleninformationen<\/span><\/b><\/p>\n<h2>F&uuml;llen der Tabelle tblTempTables<\/h2>\n<p>Beim Laden des Formulars wird in der Ereignisprozedur <b>Form_Load <\/b>die Methode <b>cboVerbindung_AfterUpdate <\/b>aufgerufen. Diese wird auch als Ereignis ausgel&ouml;st, wenn der Benutzer eine neue Verbindung &uuml;ber das Kombinationsfeld <b>cboVerbindung <\/b>ausw&auml;hlt.<\/p>\n<p>Die Prozedur <b>cboVerbindung_AfterUpdate <\/b>haben wir so angepasst, dass alle f&uuml;r die Tabelle <b>tblTablesTemp <\/b>ben&ouml;tigten Daten eingelesen werden (siehe Listing 1).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>cboVerbindung_AfterUpdate()\r\n     '' ... Deklarationen ...\r\n     <span style=\"color:blue;\">Set<\/span> dbc = CodeDb\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     dbc.Execute \"DELETE FROM tblTablesTemp\", dbFailOnError\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strBenutzername) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         strBenutzername = Nz(dbc.OpenRecordset(\"SELECT Benutzername FROM tblVerbindungszeichenfolgen \" _\r\n             & \"WHERE VerbindungszeichenfolgeID = \" & Me!cboVerbindung).Fields(0), \"\")\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strKennwort) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         strKennwort = Nz(dbc.OpenRecordset(\"SELECT Kennwort FROM tblVerbindungszeichenfolgen \" _\r\n             & \"WHERE VerbindungszeichenfolgeID = \" & Me!cboVerbindung).Fields(0), \"\")\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span>VerbindungTesten(Me!cboVerbindung, strVerbindungszeichenfolge, lngErrorNumber, strErrorDescription) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> qdf = db.CreateQueryDef(\"\")\r\n         <span style=\"color:blue;\">With<\/span> qdf\r\n             .SQL = \"SELECT TABLE_SCHEMA, TABLE_NAME, CONCAT(TABLE_SCHEMA, ''.'', TABLE_NAME) AS TABLE_SCHEMA_NAME \" _\r\n                 & \"FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE IN (''BASE TABLE'', ''VIEW'') ORDER BY TABLE_TYPE, TABLE_NAME\"\r\n             .Connect = strVerbindungszeichenfolge\r\n             .ReturnsRecords = <span style=\"color:blue;\">True<\/span>\r\n         End <span style=\"color:blue;\">With<\/span>\r\n         <span style=\"color:blue;\">Set<\/span> rstTablesSQL = qdf.OpenRecordset\r\n         <span style=\"color:blue;\">Set<\/span> rstTablesLocal = db.OpenRecordset(\"SELECT Name FROM MSysObjects WHERE NOT Connect IS NULL \" _\r\n             & \"AND NOT Name LIKE ''~*''\", dbOpenDynaset)\r\n         <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstTablesSQL.EOF\r\n             strTableSQL = rstTablesSQL!TABLE_SCHEMA_NAME\r\n             <span style=\"color:blue;\">Do While<\/span> <span style=\"color:blue;\">Not<\/span> rstTablesLocal.EOF\r\n                 strTableSource = db.TableDefs(rstTablesLocal!Name).SourceTableName\r\n                 strTableLink = \"\"\r\n                 <span style=\"color:blue;\">If <\/span>rstTablesSQL!TABLE_SCHEMA_NAME = strTableSource<span style=\"color:blue;\"> Then<\/span>\r\n                     strTableLink = rstTablesLocal!Name\r\n                     <span style=\"color:blue;\">Exit Do<\/span>\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n                 rstTablesLocal.Move<span style=\"color:blue;\">Next<\/span>\r\n             <span style=\"color:blue;\">Loop<\/span>\r\n             dbc.Execute \"INSERT INTO tblTablesTemp(TableSQL, TableLink, [Schema], [Table]) VALUES(''\" & strTableSQL & \"'', ''\" _\r\n                 & strTableLink & \"'', ''\" & rstTablesSQL!TABLE_SCHEMA & \"'', ''\" & rstTablesSQL!TABLE_NAME & \"'')\", dbFailOnError\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> rstTablesLocal.BOF<span style=\"color:blue;\"> Then<\/span>\r\n                 rstTablesLocal.MoveFirst\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             rstTablesSQL.Move<span style=\"color:blue;\">Next<\/span>\r\n         <span style=\"color:blue;\">Loop<\/span>\r\n         Me.lstTabellen.RowSource = \"SELECT TableSQL, TableLink, Schema, Table FROM tblTablesTemp ORDER BY TableSQL, TableLink\"\r\n         For i = 0 To Me.lstTabellen.ListCount\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(Me.lstTabellen.Column(1, i)) = 0<span style=\"color:blue;\"> Then<\/span>\r\n                 Me.lstTabellen.Selected(i) = <span style=\"color:blue;\">True<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">Next<\/span> i\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Keine g&uuml;ltige Verbindung.\" & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span> & strErrorDescription\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: Einlesen der Tabellendaten beim Laden des Formulars<\/span><\/b><\/p>\n<p>Wir deklarieren und initialisieren zwei <b>DAO.Database<\/b>-Variablen namens <b>dbc <\/b>und <b>db<\/b>, mit denen wir das <b>Database<\/b>-Objekt der Add-In-Datenbank und der ge&ouml;ffneten Datenbank referenzieren.<\/p>\n<p>Im ersten Schritt leeren wir die Tabelle <b>tblTablesTemp<\/b>. Dann folgen die bereits bekannten Schritte, um den aktuellen Benutzer und sein Kennwort zu ermitteln, die wir zum Testen der Verbindung mit der Funktion <b>VerbindungTesten <\/b>ben&ouml;tigen.<\/p>\n<p>Ist dieser Aufruf erfolgreich, haben wir in <b>strVerbindungszeichenfolge <\/b>eine funktionierende Zeichenkette mit den Verbindungsdaten.<\/p>\n<p>Zum Aufbau der Verbindung erstellen wir nun mit <b>CreateQueryDef <\/b>eine tempor&auml;re Abfrage, die wir mit <b>qdf <\/b>referenzieren.<\/p>\n<p>Diese versehen wir &uuml;ber die <b>SQL<\/b>-Eigenschaft mit einer Abfrage, die uns die Felder <b>TABLE_SCHEMA<\/b>, <b>TABLE_NAME <\/b>und den mit dem Schema versehenen Tabellennamen (<b>CONCAT(TABLE_SCHEMA, &#8220;.&#8220;, TABLE_NAME<\/b>) f&uuml;r das Feld <b>TABLE_SCHEMA_NAME <\/b>aus der Systemtabelle <b>INFORMATION_SCHEMA.TABLES <\/b>des SQL Servers, bei denen der Tabellentyp &uuml;ber das Kriterium <b>TABLE_TYPE IN (&#8220;BASE TABLE&#8220;, &#8220;VIEW&#8220;) <\/b>als Tabelle oder View erkannt wird.<\/p>\n<p>Die Verbindungszeichenfolge stellen wir auf den Inhalt der Variablen <b>strVerbindungszeichenfolge <\/b>ein und legen mit <b>.ReturnsRecords = True <\/b>fest, dass diese Abfrage Datens&auml;tze zur&uuml;ckliefern soll.<\/p>\n<p>Auf Basis dieser Abfrage erstellen wir mit <b>OpenRecordset <\/b>ein Recordset, das wir mit <b>rstTablesSQL <\/b>referenzieren.<\/p>\n<p>Danach erstellen wir noch ein zweites Recordset namens <b>rstTablesLocal<\/b>, das wir mit den Daten der Access-Systemtabelle <b>MSysObjects <\/b>f&uuml;llen, bei denen das Feld <b>Connect <\/b>gef&uuml;llt ist.<\/p>\n<p>Dies weist darauf hin, dass es sich um eine Tabellenverkn&uuml;pfung handelt. Die Abfrage enth&auml;lt einen weiteren Parameter, n&auml;mlich <b>NOT Name Like &#8220;~*&#8220;<\/b>.<\/p>\n<p>Er sorgt f&uuml;r den Fall vor, dass wir in der aktuellen Session, also seit dem &Ouml;ffnen der Access-Datenbank, bereits manuell Tabellenverkn&uuml;pfungen gel&ouml;scht haben.<\/p>\n<p>Diese werden nicht direkt vollst&auml;ndig gel&ouml;scht, sondern sind noch unter einem tempor&auml;ren Namen wie <b>~TMPCLP215381 <\/b>in der Datenbank vorhanden.<\/p>\n<p>Sie enthalten wie die gel&ouml;schte Tabellenverkn&uuml;pfung noch die Eigenschaft <b>Connect <\/b>und werden so zu der entsprechenden SQL Server-Tabelle zugeordnet. Damit diese in der Liste nicht angezeigt werden, geben wir den entsprechenden zus&auml;tzlichen Filter an.<\/p>\n<p>In der folgenden <b>Do While<\/b>-Schleife durchlaufen wir alle Datens&auml;tze des Recordsets <b>rstTableSQL<\/b> und schreiben dort den Namen der Tabelle in die Variable <b>strTableSQL<\/b>.<\/p>\n<p>Damit durchlaufen wir in einer inneren <b>Do While<\/b>-Schleife alle Datens&auml;tze des Recordsets mit den Tabellenverkn&uuml;pfungen. Hier lesen wir aus der Eigenschaft <b>SourceTableName <\/b>den Namen der Tabelle ein, die als Quelle f&uuml;r die Tabellenverkn&uuml;pfung dient. Dazu greifen wir &uuml;ber die <b>TableDefs<\/b>-Auflistung auf die entsprechende Tabellendefinition zu und speichern das Ergebnis in der Variablen <b>strTableSource<\/b>.<\/p>\n<p>Wenn nun der Wert der in der &auml;u&szlig;eren <b>Do While<\/b>-Schleife ermittelten SQL Server-Tabelle mit dem Namen der Quelltabelle mit der in der inneren Schleife durchlaufenen Tabelle &uuml;bereinstimmt, haben wir einen Treffer: Dann tragen wir in die Variable <b>strTableLink <\/b>(f&uuml;r die Tabellenverkn&uuml;pfung) den Namen der Tabellenverkn&uuml;pfung ein und verlassen die innere Schleife.<\/p>\n<p>Anderenfalls durchlaufen wir die lokalen Tabellen solange, bis wir eine &Uuml;bereinstimmung finden oder alle Tabellen durchlaufen wurden. Damit k&ouml;nnen wir einen neuen Datensatz in die Tabelle <b>tblTablesTemp<\/b> anlegen &#8211; unabh&auml;ngig davon, ob wir eine passende Tabellenverkn&uuml;pfung gefunden haben.<\/p>\n<p>Es kann schlie&szlig;lich auch vorkommen, dass eine Tabelle der SQL Server-Datenbank noch nicht als Tabellenverkn&uuml;pfung in der Access-Datenbank repr&auml;sentiert ist.<\/p>\n<p>Wir tragen also den Namen der SQL Server-Tabelle, den Namen der Tabellenverkn&uuml;pfung, das Schema und den reinen Tabellennamen in die Tabelle <b>tblTablesTemp <\/b>ein.<\/p>\n<p>Damit stellen wir das Recordset f&uuml;r die innere Schleife wieder auf den ersten Datensatz zur&uuml;ck und bewegen den Datensatzzeiger f&uuml;r das Recordset der &auml;u&szlig;eren Schleife zum n&auml;chsten Datensatz.<\/p>\n<h2>SQL Server-Tabellen und Tabellenverkn&uuml;pfungen im Listenfeld anzeigen<\/h2>\n<p>Bevor wir den Rest der Prozedur betrachten, schauen wir uns die notwendigen &Auml;nderungen am Listenfeld <b>lstTabellen <\/b>zur Anzeige der Tabellen im Formular <b>frmTabellenverknuepfungen <\/b>an (siehe Bild 3).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1551_014.png\" alt=\"Neuer Entwurf des Formulars frmTabellenVerknuepfen\" width=\"524,559\" height=\"410,9846\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Neuer Entwurf des Formulars frmTabellenVerknuepfen<\/span><\/b><\/p>\n<p>Hier haben wir zun&auml;chst eine Datensatzherkunft zugewiesen:<\/p>\n<pre>SELECT TableSQL, TableLink, Schema, Table FROM tblTablesTemp ORDER BY TableSQL, TableLink;<\/pre>\n<p>Damit nur die beiden Felder <b>TableSQL <\/b>und <b>TableLink <\/b>angezeigt werden, haben wir die Eigenschaften <b>Spaltenanzahl <\/b>auf <b>4 <\/b>und <b>Spaltenbreiten <\/b>auf <b>;;0cm;0cm <\/b>eingestellt. Die &uuml;brigen beiden Felder <b>Schema <\/b>und <b>Table <\/b>landen unsichtbar im Listenfeld, wodurch wir sie zwar nicht sehen, aber dennoch auf diese zugreifen k&ouml;nnen, sollte dies eventuell zum Verkn&uuml;pfen erforderlich sein.<\/p>\n<p>In der Formularansicht sieht das nun beispielsweise wie in Bild 4 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1551_020.png\" alt=\"Formularansicht des Formulars frmTabellenVerknuepfen\" width=\"524,559\" height=\"410,9846\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Formularansicht des Formulars frmTabellenVerknuepfen<\/span><\/b><\/p>\n<p>Es fehlt noch der Teil des Codes, der daf&uuml;r sorgt, dass solche Tabellen, f&uuml;r die bereits eine Verkn&uuml;pfung vorliegt, automatisch markiert werden.<\/p>\n<p>Dazu durchlaufen wir die Elemente des Listenfeldes in einer <b>For&#8230;Next<\/b>-Schleife &uuml;ber die Werte <b>0 <\/b>bis zur Anzahl der Listenelemente minus <b>1<\/b>.<\/p>\n<p>Wir pr&uuml;fen, ob die erste Spalte der aktuellen Zeile einen Eintrag mit einer L&auml;nge gr&ouml;&szlig;er als <b>0 <\/b>enth&auml;lt.<\/p>\n<p>Ist das der Fall, wird der Eintrag durch Einstellen der <b>Selected<\/b>-Auflistung f&uuml;r die Zeile mit dem entsprechenden Index auf <b>True <\/b>eingestellt.<\/p>\n<p>Damit haben wir den Teil zum Darstellen der vorliegenden SQL Server-Tabellen und der entsprechenden Tabellenverkn&uuml;pfungen bereits erledigt.<\/p>\n<h2>Erweiterte Optionen zum Verkn&uuml;pfen von Tabellen<\/h2>\n<p>Wie oben beschreiben, wollen wir nun das Verkn&uuml;pfen von Tabellen optimieren. Nochmal kurz zusammengefasst:<\/p>\n<ul>\n<li>Wenn eine Verkn&uuml;pfung vorhanden ist, soll diese je nach den Vorgaben des Benutzers entweder neu erstellt oder beibehalten werden.<\/li>\n<li>Wenn eine Verkn&uuml;pfung noch nicht vorhanden ist, soll die Verkn&uuml;pfung nach bestimmten Regeln neu erstellt werden. Diese Regeln beziehen sich auf den Namen der neuen Tabellenverkn&uuml;pfung.<\/li>\n<\/ul>\n<p>Damit der Benutzer Regeln f&uuml;r die zu verwendenden Namen aufstellen kann, haben wir dem Formular <b>frmTabellenVerknuepfen <\/b>weitere Steuerelemente hinzugef&uuml;gt.<\/p>\n<p>Hier sehen wir als Erstes ein Textfeld mit der Beschriftung <b>Name f&uuml;r neue Tabellenverkn&uuml;pfungen<\/b>. Hier k&ouml;nnen wir beliebige Texte einf&uuml;gen, aber wir sollten die Platzhalter <b>[Name]<\/b> und gegebenenfalls zus&auml;tzlich <b>[Schema] <\/b>hinzuf&uuml;gen.<\/p>\n<p>Wichtig: Wenn wir hier keinen Wert angeben, wird der Name der Tabelle ohne Schema verwendet, bei <b>dbo.tblAnlagen <\/b>also beispielsweise nur <b>tblAnlagen<\/b>.<\/p>\n<h2>Beispiele f&uuml;r die Benennung der neuen Tabellenverkn&uuml;pfungen<\/h2>\n<p>Hier sind einige Beispiele f&uuml;r die Ausdr&uuml;cke, die im Feld <b>Name f&uuml;r neue Tabellenverkn&uuml;pfungen <\/b>angegeben werden k&ouml;nnen:<\/p>\n<ul>\n<li><b>[Name]<\/b>: Legt nur den Namen der SQL Server-Tabelle ohne Schema als Bezeichnung der Tabellenverkn&uuml;pfung fest.<\/li>\n<li><b>Keine Angabe<\/b>: Legt ebenfalls den Namen der SQL Server-Tabelle ohne Schema als Bezeichnung der Tabellenverkn&uuml;pfung fest.<\/li>\n<li><b>[Schema]_[Name]<\/b>: Legt die SQL Server-Tabelle <b>dbo.tblAnlagen <\/b>unter dem Namen <b>dbo_tblAnlagen <\/b>als Tabellenverkn&uuml;pfung an.<\/li>\n<li><b>sql_[Name]<\/b>: Legt die SQL Server-Tabelle <b>dbo.tblAnlagen <\/b>unter dem Namen <b>sql_tblAnlagen <\/b>als Tabellenverkn&uuml;pfung an.<\/li>\n<\/ul>\n<p>Beachten Sie, dass die Regeln f&uuml;r die Benennung von Access-Objekten hier ber&uuml;cksichtigt werden &#8211; also nur alphanumerische Zeichen und der Unterstrich. Es sind zwar auch andere Zeichen m&ouml;glich, aber ung&uuml;nstig.<\/p>\n<h2>Option &#8222;Vorhandene Tabellen immer &uuml;berschreiben&#8220;<\/h2>\n<p>Diese Option sorgt daf&uuml;r, dass alle Tabellenverkn&uuml;pfungen, die im Listenfeld markiert sind, gel&ouml;scht und neu angelegt werden. Das f&uuml;hrt auch dazu, dass die neuen Tabellenverkn&uuml;pfungen unter Ber&uuml;cksichtigung der angegebenen Benennungskonvention erstellt werden.<\/p>\n<p>Wenn man also beispielsweise eine Migration der Datenbank mit dem SQL Server Migration Assistant durchgef&uuml;hrt hat, wurden die Tabellenverkn&uuml;pfungen &uuml;blicherweise mit <b>dbo_Tabellenname <\/b>benannt.<\/p>\n<p>Dann sollte man, wenn man die Tabellen mit der hier vorgestellten L&ouml;sung neu verkn&uuml;pft, auch das Format <b>[Schema]_[Name] <\/b>einstellen.<\/p>\n<h2>Durchf&uuml;hrung der Verkn&uuml;pfung<\/h2>\n<p>Nachdem wir festgelegt haben, welche Tabellen verkn&uuml;pft werden sollen und nach welchem Schema, k&ouml;nnen wir auf die Schaltfl&auml;che <b>cmdTabellenVerknuepfen <\/b>klicken. Diese ruft die Prozedur aus Listing 2 auf.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>cmdTabellenVerknuepfen_Click()\r\n     <span style=\"color:blue;\">Dim <\/span>strTableLocal<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strTableSQL<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strTableNew<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngIndex<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngConnected<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>lngSelected<span style=\"color:blue;\"> As Long<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strVerbindungszeichenfolge<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(Nz(Me.txtNeuerName, \"\")) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">InStr<\/span>(1, Me.txtNeuerName, \"[Name]\") = 0<span style=\"color:blue;\"> Then<\/span>\r\n             <span style=\"color:blue;\">If <\/span>Me.lstTabellen.ItemsSelected.Count &gt; 1<span style=\"color:blue;\"> Then<\/span>\r\n                 <span style=\"color:blue;\">MsgBox<\/span> \"Der Ausdruck f&uuml;r den neuen Namen der Verkn&uuml;pfung muss zumindest den Platzhalter [Name] \" _\r\n                     & \"enthalten.\" & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span> & \"Wenn das nicht der Fall ist, kann nur eine Verkn&uuml;pfung \" _\r\n                     & \"angelegt werden.\" & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span> & \" Der Vorgang wird abgebrochen.\", vbOKOnly + _\r\n                     vbExclamation, \"Fehlender Platzhalter\"\r\n                 <span style=\"color:blue;\">Exit Sub<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">If <\/span>VerbindungTesten(Me!cboVerbindung, strVerbindungszeichenfolge) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         For lngSelected = 0 To Me!lstTabellen.ItemsSelected.Count - 1\r\n             lngIndex = Me.lstTabellen.ItemsSelected(lngSelected)\r\n             strTableSQL = Me.lstTabellen.Column(0, lngIndex)\r\n             strTableLocal = Me.lstTabellen.Column(1, lngIndex)\r\n             strTable<span style=\"color:blue;\">New<\/span> = <span style=\"color:blue;\">Replace<\/span>(<span style=\"color:blue;\">Replace<\/span>(Nz(Me.txtNeuerName, \"\"), \"[Schema]\", Me.lstTabellen.Column(2, lngIndex)), _\r\n                 \"[Name]\", Me.lstTabellen.Column(3, lngIndex))\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strTable<span style=\"color:blue;\">New<\/span>) = 0<span style=\"color:blue;\"> Then<\/span>\r\n                 strTable<span style=\"color:blue;\">New<\/span> = Me.lstTabellen.Column(3, lngIndex)\r\n             <span style=\"color:blue;\">End If<\/span>\r\n             If TabelleVerknuepfen(strTableLocal, strTableNew, strTableSQL, strVerbindungszeichenfolge, _\r\n                     Me!chkImmerUeberschreiben) = <span style=\"color:blue;\">True<\/span> Then\r\n                 lngConnected = lngConnected + 1\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">Next<\/span> lngSelected\r\n         <span style=\"color:blue;\">Call<\/span> cboVerbindung_AfterUpdate\r\n         <span style=\"color:blue;\">MsgBox<\/span> lngConnected & \" Tabellen wurden verkn&uuml;pft.\"\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">MsgBox<\/span> \"Verbindung konnte nicht hergestellt werden.\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Call<\/span> VerknuepfungInDatenbankSpeichern(Me.cboVerbindung)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Aufruf der Verkn&uuml;pfung von Tabellen<\/span><\/b><\/p>\n<p>Die Prozedur deklariert drei Variablen f&uuml;r die Benennung von Tabellen:<\/p>\n<ul>\n<li><b>strTableSQL<\/b>: Name der Tabelle im SQL Server (siehe erste Spalte im Listenfeld)<\/li>\n<li><b>strTableLocal<\/b>: Name der Tabellenverkn&uuml;pfung, die mit der Tabelle aus <b>strTableSQL <\/b>verkn&uuml;pft ist &#8211; sofern vorhanden, sonst leer.<\/li>\n<li><b>strTableNew<\/b>: Neuer Name f&uuml;r die Tabellenverkn&uuml;pfung mit der Tabelle aus <b>strTableSQL<\/b>. Kann mit <b>strTableLocal <\/b>&uuml;bereinstimmen, muss es aber nicht.<\/li>\n<\/ul>\n<p>Als Erstes pr&uuml;ft die Prozedur, ob die Bedingungen f&uuml;r das Ersetzen der Tabellenverkn&uuml;pfungen erf&uuml;llt sind. Wenn der Benutzer im Textfeld <b>txtNeuerName <\/b>nicht den Platzhalter <b>[Name] <\/b>eintr&auml;gt, der den Tabellennamen aus dem SQL Server widerspiegelt und dieses Textfeld auch nicht leer l&auml;sst, kann er nur eine Verkn&uuml;pfung neu erstellen.<\/p>\n<p>Der Grund ist, dass mit dem statischen Namen f&uuml;r die neue Verkn&uuml;pfung sonst mehrere neue Verkn&uuml;pfungen den gleichen Namen erhalten w&uuml;rden, was beim Anlegen des ersten doppelten Objekts zu einem Fehler f&uuml;hren w&uuml;rde.<\/p>\n<p>Also pr&uuml;fen wir zuerst, ob <b>txtNeuerName <\/b>nicht leer ist. Ist das Textfeld leer, verwendet das Formular automatisch den Namen der SQL Server-Tabelle f&uuml;r die Tabellenverkn&uuml;pfung und wir haben individuelle Namen je Tabellenverkn&uuml;pfung.<\/p>\n<p>Ist es nicht leer, pr&uuml;ft die Prozedur, ob der Benutzer den Platzhalter <b>[Name] <\/b>in den Ausdruck f&uuml;r den Namen der neuen Tabellenverkn&uuml;pfungen integriert hat.<\/p>\n<p>Anderenfalls pr&uuml;ft sie, ob der Benutzer mehr als einen Eintrag der Liste zum Aktualisieren der Verkn&uuml;pfung ausgew&auml;hlt hat. Ist das der Fall, erscheint eine Meldung, dass dies nicht m&ouml;glich ist und die Prozedur wird abgebrochen.<\/p>\n<p>Ist das nicht der Fall, pr&uuml;ft die Prozedur mit einem Aufruf der Funktion <b>VerbindungTesten <\/b>wieder, ob die Verbindung funktioniert, und liefert mit <b>strVerbindungszeichenfolge <\/b>die aktuelle Verbindungszeichenfolge zur&uuml;ck.<\/p>\n<p>Dann durchl&auml;uft die Prozedur in einer <b>For&#8230;Next<\/b>-Schleife alle Elemente des Listenfeldes <b>lstTabellen<\/b>. Dabei werden die Werte von <b>0 <\/b>bis zur Anzahl der Listenelement minus <b>1 <\/b>verwendet.<\/p>\n<p>In die Variable <b>strTableSQL <\/b>liest die Prozedur den Wert der ersten Spalte mit dem Index <b>0 <\/b>des Listenfeldes ein, also den Namen der SQL Server-Tabelle. In <b>strTableLocal <\/b>landet der Wert der zweiten Spalte. Dieser kann auch leer sein, wenn es noch keine Tabellenverkn&uuml;pfung gibt, die sich auf die aktuelle SQL Server-Tabelle bezieht. Schlie&szlig;lich schreiben wir in die Variable <b>strTableNew <\/b>den durch den Benutzer definierten Namen f&uuml;r die neu anzulegende Tabellenverkn&uuml;pfung.<\/p>\n<p>Dabei verwendet die Prozedur den Text des Feldes <b>txtNeuerName<\/b>, indem sich beispielsweise ein Ausdruck wie <b>[Schema]_[Name] <\/b>befindet, und ersetzt die Platzhalter <b>[Schema] <\/b>und <b>[Name] <\/b>durch die Werte der dritten und vierten Spalte des Listenfeldes f&uuml;r den aktuellen Eintrag.<\/p>\n<p>Wenn <b>strTableNew <\/b>danach noch leer sein sollte, was der Fall ist, wenn der Benutzer keinen Wert in das Textfeld <b>txtNeuerName <\/b>eingetragen hat, tr&auml;gt die Prozedur einfach den Namen der SQL Server-Tabelle als Namen der anzulegenden Tabellenverkn&uuml;pfung an.<\/p>\n<p>Danach ruft sie die Funktion <b>TabelleVerknuepfen <\/b>auf und &uuml;bergibt dieser die drei Variablen <b>strTableLocal<\/b>, <b>strTableNew <\/b>und <b>strTableSQL <\/b>als Parameter sowie die Verbindungszeichenfolge und den Wert der Option aus <b>chkImmerUeberschreiben<\/b>.<\/p>\n<p>Liefert diese den Wert <b>True<\/b> zur&uuml;ck, wurde die Tabellenverkn&uuml;pfung erfolgreich angelegt und wir erh&ouml;hen den Wert des Z&auml;hlers <b>lngConnected <\/b>um <b>1<\/b>. Damit z&auml;hlen wir die Anzahl der erfolgreich hinzugef&uuml;gten Tabellenverkn&uuml;pfungen und geben diese anschlie&szlig;end aus.<\/p>\n<p>Damit rufen wir nochmal die Prozedur <b>cboVerbindung_AfterUpdate <\/b>auf, damit die aktualisierten Tabellenverkn&uuml;pfungen im Listenfeld angezeigt werden k&ouml;nnen und geben die Anzahl der aktualisierten Elemente in einem Meldungsfenster aus.<\/p>\n<h2>Verkn&uuml;pfen der Tabelle in der Funktion &#8222;TabelleVerknuepfen&#8220;<\/h2>\n<p>Die Funktion aus Listing 3 erledigt die Hauptarbeit. Sie nimmt die von der aufrufenden Prozedur &uuml;bergebenen Parameter entgegen und deklariert ein <b>TableDef<\/b>-Objekt zum Anlegen der Tabellenverkn&uuml;pfung.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>TabelleVerknuepfen(strTableLocal<span style=\"color:blue;\"> As String<\/span>, strTableNew<span style=\"color:blue;\"> As String<\/span>, ByVal strTableSQL<span style=\"color:blue;\"> As String<\/span>, _\r\n         strVerbindungszeichenfolge<span style=\"color:blue;\"> As String<\/span>, bolImmerUeberschreiben<span style=\"color:blue;\"> As Boolean<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\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>tdf<span style=\"color:blue;\"> As <\/span>dao.TableDef\r\n     \r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     <span style=\"color:blue;\">If <\/span>bolImmerUeberschreiben = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(strTableLocal) = 0<span style=\"color:blue;\"> Then<\/span>\r\n             db.TableDefs.Delete strTableLocal\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(strTableLocal) = 0<span style=\"color:blue;\"> Then<\/span>\r\n             strTable<span style=\"color:blue;\">New<\/span> = InputBox(\"Das Objekt namens ''\" & strTableLocal & \"'' ist bereits mit der \" _\r\n                 & \"SQL Server-Tabelle ''\" & strTableSQL & \"'' verkn&uuml;pft.\" & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span> _\r\n                 & \"Klicke auf OK, um es zu l&ouml;schen, und unter dem folgenden Namen neu zu erstellen.\" & <span style=\"color:blue;\">vbCrLf<\/span> _\r\n                 & <span style=\"color:blue;\">vbCrLf<\/span> & \"Du kannst den Namen auch manuell anpassen.\" & <span style=\"color:blue;\">vbCrLf<\/span> & <span style=\"color:blue;\">vbCrLf<\/span> _\r\n                 & \"Oder klicke auf Abbrechen, um die Tabellenverkn&uuml;pfung nicht zu erstellen.\", _\r\n                 \"Bereits vorhandenes Objekt\", strTable<span style=\"color:blue;\">New<\/span>)\r\n             <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Len<\/span>(strTable<span style=\"color:blue;\">New<\/span>) = 0<span style=\"color:blue;\"> Then<\/span>\r\n                 TabelleVerknuepfen = <span style=\"color:blue;\">False<\/span>\r\n                 <span style=\"color:blue;\">Exit Function<\/span>\r\n             <span style=\"color:blue;\">Else<\/span>\r\n                 <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(strTableLocal) = 0<span style=\"color:blue;\"> Then<\/span>\r\n                     db.TableDefs.Delete strTableLocal\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n             <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> tdf = db.CreateTableDef(strTable<span style=\"color:blue;\">New<\/span>)\r\n     tdf.Connect = strVerbindungszeichenfolge\r\n     tdf.SourceTableName = strTableSQL\r\n     db.TableDefs.Append tdf\r\n     db.TableDefs(strTable<span style=\"color:blue;\">New<\/span>).RefreshLink\r\n     Application.RefreshDatabaseWindow\r\n     TabelleVerknuepfen = <span style=\"color:blue;\">True<\/span>\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Funktion zum Erstellen oder Aktualisieren von Tabellenverkn&uuml;pfungen<\/span><\/b><\/p>\n<p>Sie pr&uuml;ft als Erstes, ob der Parameter <b>bolImmerUeberschreiben <\/b>den Wert <b>True <\/b>liefert. In diesem Fall soll die Tabellenverkn&uuml;pfung auf jeden Fall gel&ouml;scht werden, was mit der <b>Delete<\/b>-Methode der <b>TableDefs<\/b>-Auflistung f&uuml;r die Tabellenverkn&uuml;pfung aus <b>strTableLocal <\/b>geschieht.<\/p>\n<p>Hat <b>bolImmerUeberschreiben <\/b>nicht den Wert <b>True<\/b>, untersuchen wir die Aufgabe genauer, wobei wir auch auf die Unterst&uuml;tzung des Benutzers zur&uuml;ckgreifen.<\/p>\n<p>Danach pr&uuml;ft die Prozedur, ob <b>strTableLocal<\/b> aktuell &uuml;berhaupt gef&uuml;llt ist, also ob es f&uuml;r die aktuelle SQL Server-Tabelle bereits eine Tabellenverkn&uuml;pfung gibt. Ist das der Fall, k&ouml;nnen wir gleich zum n&auml;chsten Schritt springen. Wenn es allerdings bereits eine Tabellenverkn&uuml;pfung f&uuml;r die Tabelle gibt, m&uuml;ssen wir ein paar weitere Schritte unternehmen.<\/p>\n<p>Dabei zeigen wir eine <b>InputBox <\/b>an, die wie in Bild 5 aussieht und die den Namen der aktuellen Tabellenverkn&uuml;pfung f&uuml;r die SQL Server-Tabelle anzeigt und auch den Namen der SQL Server-Tabelle.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1551_021.png\" alt=\"R&uuml;ckfrage, unter welchem Namen die Verkn&uuml;pfung angelegt werden soll.\" width=\"649,559\" height=\"403,0596\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: R&uuml;ckfrage, unter welchem Namen die Verkn&uuml;pfung angelegt werden soll.<\/span><\/b><\/p>\n<p>Unten zeigt die InputBox den zuvor ermittelten Namen f&uuml;r die neu zu erstellende Tabellenverkn&uuml;pfung an.<\/p>\n<p>Der Benutzer hat nun die folgenden M&ouml;glichkeiten:<\/p>\n<ul>\n<li>Er kann auf <b>OK <\/b>klicken und den Namen f&uuml;r die neue Tabellenverkn&uuml;pfung, hier <b>dbo_tblAnlagen<\/b>, &uuml;bernehmen. <\/li>\n<li>Er kann den Namen zuvor nach seinen eigenen W&uuml;nschen anpassen, zum Beispiel in <b>Anlagen<\/b>.<\/li>\n<li>Oder er klickt auf <b>Abbrechen <\/b>und sorgt so daf&uuml;r, dass das Ergebnis der <b>InputBox<\/b>-Funktion eine leere Zeichenkette ist.<\/li>\n<\/ul>\n<p>Wie auch immer er sich entscheidet, landet das Ergebnis in der Variablen <b>strTableNew<\/b>.<\/p>\n<p>Hat diese die L&auml;nge <b>0<\/b>, hat der Benutzer auf <b>Abbrechen <\/b>geklickt und die Tabelle soll nicht verkn&uuml;pft werden. Dann wird als Funktionswert <b>False <\/b>zur&uuml;ckgeliefert und die Funktion wird beendet.<\/p>\n<p>Anderenfalls pr&uuml;ft die Prozedur, ob bereits eine Tabellenverkn&uuml;pfung f&uuml;r diese Tabelle vorhanden war und l&ouml;scht diese gegebenenfalls.<\/p>\n<p>Anschlie&szlig;end folgt das Anlegen der neuen Tabellenverkn&uuml;pfung. Mit der <b>CreateTableDef<\/b>-Methode erstellt die Funktion ein neues <b>TableDef<\/b>-Objekt mit dem Namen aus <b>strTableNew<\/b>.<\/p>\n<p>Sie stellt die Verbindungszeichenfolge des <b>TableDef<\/b>-Objekts auf den Inhalt aus <b>strVerbindungszeichenfolge <\/b>ein und die Quelltabelle auf die Tabelle aus <b>strTableSQL<\/b>. Dann h&auml;ngt sie das neue <b>TableDef<\/b>-Objekt an die <b>TableDefs<\/b>-Auflistung an und aktualisiert die Tabellenverkn&uuml;pfung mit der <b>RefreshLink<\/b>-Methode.<\/p>\n<p>Schlie&szlig;lich aktualisiert die Methode <b>RefreshDatabaseWindow<\/b> auch noch den Navigationsbereich von Access und sorgt so f&uuml;r die Anzeige der neu erstellten Tabellenverkn&uuml;pfungen.<\/p>\n<p>Als Funktionswert liefert die Funktion den Wert <b>True <\/b>zur&uuml;ck.<\/p>\n<h2>Optimierung: Alle Listeneintr&auml;ge markieren oder abw&auml;hlen<\/h2>\n<p>Wenn wir ein wenig mit der Listenansicht experimentieren, sehen wir, dass wir bei der ausgew&auml;hlten Einstellung <b>Erweitert <\/b>f&uuml;r die Eigenschaft <b>Mehrfachauswahl <\/b>nicht einfach mit einer Tastenkombination wie <b>Strg + A <\/b>alle Eintr&auml;ge selektieren k&ouml;nnen.<\/p>\n<p>Dies w&auml;re jedoch w&uuml;nschenswert &#8211; vor allem f&uuml;r SQL Server-Datenbanken, die sehr viele Tabellen enthalten und die als Tabellenverkn&uuml;pfung hinzugef&uuml;gt oder aktualisiert werden sollen.<\/p>\n<p>Wir k&ouml;nnen lediglich bei gedr&uuml;ckter <b>Strg<\/b>-Taste einzelne Eintr&auml;ge hinzuf&uuml;gen oder abw&auml;hlen oder bei gedr&uuml;ckter Umschalttaste den ersten und den letzten auszuw&auml;hlenden Eintrag selektieren.<\/p>\n<p>F&uuml;r das Selektieren aller Eintr&auml;ge k&ouml;nnen wir beispielsweise Folgendes erledigen:<\/p>\n<ul>\n<li>Programmieren einer entsprechenden Tastenkombination<\/li>\n<li>Hinzuf&uuml;gen einer Schaltfl&auml;che f&uuml;r diese Funktion<\/li>\n<\/ul>\n<p>Wir wollen hier die Methode mit der Tastenkombination hinzuf&uuml;gen.<\/p>\n<h2>Alle Listeneintr&auml;ge mit Strg + A selektieren<\/h2>\n<p>F&uuml;r diese Variante f&uuml;gen wir dem Ereignis <b>Bei Taste ab <\/b>des Listenfeldes die Ereignisprozedur aus Listing 4 hinzu.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>lstTabellen_KeyDown(KeyCode<span style=\"color:blue;\"> As Integer<\/span>, Shift<span style=\"color:blue;\"> As Integer<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>lngIndex<span style=\"color:blue;\"> As Long<\/span>\r\n     Select Case Shift\r\n         <span style=\"color:blue;\">Case <\/span>acCtrlMask\r\n             Select Case KeyCode\r\n                 <span style=\"color:blue;\">Case <\/span>vbKeyA\r\n                     For lngIndex = 0 To Me.lstTabellen.ListCount - 1\r\n                         Me.lstTabellen.Selected(lngIndex) = <span style=\"color:blue;\">True<\/span>\r\n                     <span style=\"color:blue;\">Next<\/span> lngIndex\r\n                     KeyCode = 0\r\n             <span style=\"color:blue;\">End Select<\/span>\r\n     <span style=\"color:blue;\">End Select<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Ereignisprozedur zum Selektieren aller Eintr&auml;ge des Listenfeldes<\/span><\/b><\/p>\n<p>Die Prozedur nimmt mit <b>KeyCode <\/b>einen Zahlenwert entgegen, welcher der gedr&uuml;ckten Taste entspricht, und <b>Shift<\/b> liefert einen Hinweis darauf, ob der Benutzer diese Taste in Kombination mit einer der Tasten <b>Umschalt<\/b>, <b>Strg <\/b>oder <b>Alt <\/b>bet&auml;tigt hat.<\/p>\n<p>Wir wollen zun&auml;chst nur auf solche Tastenkombinationen reagieren, bei denen der Benutzer auch die <b>Strg<\/b>-Taste gedr&uuml;ckt h&auml;lt. Dazu erstellen wir eine <b>Select Case<\/b>-Bedingung, die den Wert des Parameters <b>Shift <\/b>untersucht.<\/p>\n<p>Liefert dieser den Wert <b>acCtrlMask<\/b>, was der Taste <b>Strg <\/b>entspricht, fahren wir mit einer weiteren <b>Select Case<\/b>-Bedingung fort. Diese muss f&uuml;r die Taste <b>A <\/b>den Wert <b>vbKeyA <\/b>enthalten.<\/p>\n<p>Ist das der Fall, durchlaufen wir in einer <b>For&#8230;Next<\/b>-Schleife alle Elemente des Listenfeldes und stellen die Eigenschaft <b>Selected <\/b>f&uuml;r das jeweilige Element, das wir &uuml;ber den Index aus <b>lngIndex <\/b>ermitteln, auf <b>True <\/b>ein.<\/p>\n<p>Als Ergebnis werden nun beim Bet&auml;tigen von <b>Strg + A<\/b> alle Eintr&auml;ge des Listenfeldes aktiviert (siehe Bild 6).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1551_016.png\" alt=\"Markieren aller Listeneintr&auml;ge\" width=\"499,5589\" height=\"371,719\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Markieren aller Listeneintr&auml;ge<\/span><\/b><\/p>\n<h2>Filtern des Listenfeldes nach Tabellennamen<\/h2>\n<p>F&uuml;r Datenbanken mit sehr vielen Tabellen bietet es sich au&szlig;erdem an, die im Listenfeld angezeigten Elemente durch eine einfache Filterfunktion filtern zu k&ouml;nnen. <\/p>\n<p>Dazu hinterlegen wir im Formular ein Textfeld namens <b>txtFiltern <\/b>(siehe Bild 7). Dieses soll nach der Eingabe eines jeden Buchstaben die Tabellen der SQL Server-Datenbank filtern.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1551_017.png\" alt=\"Filtern nach Tabellennamen\" width=\"499,5589\" height=\"230,0253\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Filtern nach Tabellennamen<\/span><\/b><\/p>\n<p>Der Filter soll sich sowohl auf die Namen der Tabellen der SQL Server-Datenbank als auch auf die Namen der Tabellenverkn&uuml;pfungen auswirken.<\/p>\n<p>Dazu hinterlegen wir f&uuml;r das Ereignis <b>Bei &Auml;nderung <\/b>die Ereignisprozedur aus Listing 5.<\/p>\n<pre><span style=\"color:blue;\">Private Sub <\/span>txtFiltern_Change()\r\n     <span style=\"color:blue;\">Dim <\/span>strVergleichswert<span style=\"color:blue;\"> As String<\/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>strFilter<span style=\"color:blue;\"> As String<\/span>\r\n     strVergleichswert = Me!txtFiltern.Text\r\n     strSQL = \"SELECT TableSQL, TableLink, Schema, Table FROM tblTablesTemp[Filter] ORDER BY TableSQL, TableLink\"\r\n     <span style=\"color:blue;\">If <\/span><span style=\"color:blue;\">Not<\/span> <span style=\"color:blue;\">Len<\/span>(strVergleichswert) = 0<span style=\"color:blue;\"> Then<\/span>\r\n         strFilter = \" WHERE (TableSQL LIKE ''*\" & strVergleichswert & \"*'' OR TableLink LIKE ''*\" & strVergleichswert _\r\n             & \"*'')\"\r\n         Me.lstTabellen.RowSource = <span style=\"color:blue;\">Replace<\/span>(strSQL, \"[Filter]\", strFilter)\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         Me.lstTabellen.RowSource = <span style=\"color:blue;\">Replace<\/span>(strSQL, \"[Filter]\", \"\")\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Call<\/span> cboVerbindung_AfterUpdate\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Ereignisprozedur zum Filtern der Tabellen im Listenfeld<\/span><\/b><\/p>\n<p>Die Prozedur schreibt den Inhalt des Textfeldes in die Variable <b>strVergleichswert<\/b>. Den Inhalt m&uuml;ssen wir &uuml;ber die <b>Text<\/b>-Eigenschaft auslesen, weil wir bereits darauf zugreifen wollen, w&auml;hrend wir noch den Suchbegriff eingeben.<\/p>\n<p>In der Variablen <b>strSQL <\/b>speichern wir die eigentliche Abfrage, deren Ergebnis im Listenfeld angezeigt wird.<\/p>\n<p>Hier f&uuml;gen wir hinter der Angabe der Tabelle <b>tblTablesTemp <\/b>jedoch einen Platzhalter namens <b>[Filter] <\/b>ein.<\/p>\n<p>Wenn <b>strVergleichswert <\/b>einen Wert enth&auml;lt, stellen wir in der Variablen <b>strFilter <\/b>die <b>WHERE<\/b>-Bedingung f&uuml;r die Abfrage zusammen.<\/p>\n<p>Diese sieht bei der Angabe der Zeichenkette <b>tbl <\/b>beispielsweise wie folgt aus:<\/p>\n<pre>WHERE (TableSQL LIKE ''*tbl*'' OR TableLink LIKE ''*tbl*'')<\/pre>\n<p>F&uuml;r die Eigenschaft <b>RowSource <\/b>weisen wir dem Listenfeld dann die Abfrage zu, in der wir mit der <b>Replace<\/b>-Funktion den Platzhalter <b>[Filter] <\/b>durch den Wert aus <b>strFilter <\/b>ersetzt haben. Das sieht f&uuml;r unser Beispiel so aus:<\/p>\n<pre>SELECT TableSQL, TableLink, Schema, Table FROM tblTablesTemp WHERE (TableSQL LIKE ''*tbl*'' OR TableLink LIKE ''*tbl*'') ORDER BY TableSQL, TableLink<\/pre>\n<p>Damit erhalten wir die gefilterten Tabellen.<\/p>\n<h2>Access-Add-In per Ribbon starten<\/h2>\n<p>Mit der Erweiterung in diesem Beitrag haben wir den Tabellenverkn&uuml;pfungs-Assistenten noch ein wenig praxistauglicher gemacht.<\/p>\n<p>Damit lassen sich nun sowohl Tabellen und Views aus dem SQL Server auf einfache Art und Weise als Tabellenverkn&uuml;pfungen abbilden.<\/p>\n<p>Dabei spielt es keine Rolle, ob es bereits eine Tabellenverkn&uuml;pfung f&uuml;r eine bestimmte Tabelle gibt oder nicht.<\/p>\n<p>Ein spannendes Feature ist auch, dass wir bei der Gestaltung der Bezeichnungen f&uuml;r die Tabellenverkn&uuml;pfungen einige Freiheiten haben.<\/p>\n<p>Wir k&ouml;nnen mit Platzhaltern wie <b>[Schema] <\/b>oder <b>[Name] <\/b>die Informationen aus dem SQL Server dynamisch in eigene Formen f&uuml;r die Bezeichnungen einbauen.<\/p>\n<p>Spannend w&auml;re es nun noch, das Access-Add-In mit dieser L&ouml;sung nicht nur &uuml;ber den Ribbon-Befehl <b>Datenbanktools|Add-Ins|Add-Ins <\/b>ausf&uuml;hren zu k&ouml;nnen, sondern auch noch &uuml;ber individuelle Ribbon-Schaltfl&auml;chen an den entsprechenden Stellen &#8211; also beispielsweise im Tab <b>Externe Daten<\/b>.<\/p>\n<p>Hier wollen wir eine neue Gruppe namens <b>amvTableLinker <\/b>hinzuf&uuml;gen, die als einzigen Befehl den Eintrag <b>Verkn&uuml;pfungen aktualisieren <\/b>enthalten soll (siehe Bild 8).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1551_018.png\" alt=\"Starten des Access-Add-Ins per Ribbon-Befehl\" width=\"649,559\" height=\"478,2124\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 8: Starten des Access-Add-Ins per Ribbon-Befehl<\/span><\/b><\/p>\n<p>Dies scheint uns wesentlich intuitiver als der &uuml;bliche Weg, bei dem wir zuerst auf den Ribbon-Reiter <b>Datenbanktools<\/b> klicken, dann auf die Gruppe <b>Add-Ins <\/b>und dort mit einem Klick auf <b>Add-Ins <\/b>die Liste der verf&uuml;gbaren Add-Ins &ouml;ffnen. Hier m&uuml;ssen wir dann, je nachdem, wie viele Add-Ins hier bereits installiert wurden, auch noch einmal nach dem richtigen Add-In suchen (siehe Bild 9).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2025_03\/pic_1551_019.png\" alt=\"&Uuml;blicher Weg, um ein Access-Add-In zu starten\" width=\"700\" height=\"320,9433\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 9: &Uuml;blicher Weg, um ein Access-Add-In zu starten<\/span><\/b><\/p>\n<p>Das k&ouml;nnen wir jedoch, wie auch im ersten Beispiel gezeigt, mit etwas Zusatzaufwand erledigen. Dazu ben&ouml;tigen wir erst einmal ein COM-Add-In, das eine f&uuml;r alle ge&ouml;ffneten Access-Anwendungen sichtbare Ribbon-Erweiterung hinzuf&uuml;gt.<\/p>\n<p>Nachdem wir dies erledigt haben, folgt der spannende Teil: Wie bekommen wir es hin, dass wir &uuml;ber das Anklicken eines Ribbon-Befehls ein Access-Add-In starten?<\/p>\n<p>Wenn man es wei&szlig;, ist es eigentlich ganz einfach, aber auf die folgende Idee muss man erst einmal kommen:<\/p>\n<p>Unser COM-Add-In bekommt beim Starten von Access aus einen Verweis auf die aktuelle Access-Instanz, also ein Objekt des Typs <b>Access.Application<\/b>.<\/p>\n<p>Damit k&ouml;nnen wir mit der <b>Run<\/b>-Methode des <b>Application<\/b>-Objekts theoretisch alle &ouml;ffentlich deklarierten <b>Function<\/b>-Prozeduren aufrufen.<\/p>\n<p>Dies gilt allerdings nur f&uuml;r die Prozeduren, die sich im aktuellen VBA-Projekts der Access-Anwendung befinden.<\/p>\n<p>Um auch auf die Elemente des Access-Add-Ins zugreifen zu k&ouml;nnen, m&uuml;ssen wir das Application-Objekt des Access-Add-Ins referenzieren.<\/p>\n<p>Und das gelingt wiederum nur &uuml;ber den folgenden Trick: <\/p>\n<p>Wir &uuml;bergeben der Methode <b>Run <\/b>nicht allein den Namen der aufzurufenden Funktion, sondern auch noch den Pfad zu der Access-Add-In-Datenbank, in der sich die aufzurufende Funktion befindet. <\/p>\n<p>Das k&ouml;nnen wir auch vom VBA-Projekt von Access aus erledigen, indem wir im Direktbereich den folgenden Befehl eingeben:<\/p>\n<pre>Access.Application.Run \"C:\\Users\\User\\AppData\\Roaming\\Microsoft\\AddIns\\amvTableLinker.Autostart\\Microsoft\\AddIns\\amvTableLinker.Autostart\"<\/pre>\n<p>Um nicht f&uuml;r jeden Rechner\/Benutzer den Pfad anpassen zu m&uuml;ssen, k&ouml;nnen wir noch folgende Abk&uuml;rzung verwenden, um das Benutzerverzeichnis zu ermitteln:<\/p>\n<pre>Access.Application.Run Environ(\"AppData\") & \"\\Microsoft\\AddIns\\amvTableLinker.Autostart\"<\/pre>\n<p>Und wenn wir auf diese Weise vom VBA-Editor einer Access-Datenbank das Add-In &ouml;ffnen k&ouml;nnen, dann ist es auch &uuml;ber ein COM-Add-In m&ouml;glich, das ja auf das <b>Access.Application<\/b>-Objekt zugreifen kann.<\/p>\n<p>Wie wir ein solches COM-Add-In bauen k&ouml;nnen, zeigen wir in der folgenden Ausgabe unter dem Titel <b>Access-Add-Ins per COM-Add-In starten <\/b>(<b>www.access-im-unternehmen.de\/1552<\/b>).<\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>amvTableLinker.accda<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/A64553BA-DFB1-4FF2-9C59-067F26CB967D\/aiu_1551.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Der SQL Server-Tabellenverkn&uuml;pfungsassistent, den wir im Beitrag &#8222;SQL Server-Tabellenverkn&uuml;pfungsassistent&#8220; (www.access-im-unternehmen.de\/1540) vorgestellt haben, funktioniert in vielen Settings bereits recht gut. Die generelle Praxistauglichkeit zeigt sichjedoch erst, wenn die Anwendung einmal auf andere Benutzer und\/oder Verwendungszwecke st&ouml;&szlig;t. Da dies nun geschehen ist, wollen wir im zweiten Teil der Beitragsreihe zum Thema SQL Server-Tabellenverkn&uuml;pfungsassistent einige &Auml;nderungen und Erweiterungen nachreichen. Dabei geht es im Wesentlichen um die Benennung der Tabellenverkn&uuml;pfungen, die von dem Assistenten entweder initial angelegt oder aktualisiert werden sollen.<\/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,66032025,44000027],"tags":[],"class_list":["post-55001551","post","type-post","status-publish","format-standard","hentry","category-662025","category-66032025","category-Loesungen"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>SQL Server-Tabellenverkn&uuml;pfungsassistent, Teil 2 - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"SQL Server-Tabellenverkn&uuml;pfungsassistent, Teil 2\" \/>\n<meta property=\"og:description\" content=\"Der SQL Server-Tabellenverkn&uuml;pfungsassistent, den wir im Beitrag &quot;SQL Server-Tabellenverkn&uuml;pfungsassistent&quot; (www.access-im-unternehmen.de\/1540) vorgestellt haben, funktioniert in vielen Settings bereits recht gut. Die generelle Praxistauglichkeit zeigt sichjedoch erst, wenn die Anwendung einmal auf andere Benutzer und\/oder Verwendungszwecke st&ouml;&szlig;t. Da dies nun geschehen ist, wollen wir im zweiten Teil der Beitragsreihe zum Thema SQL Server-Tabellenverkn&uuml;pfungsassistent einige &Auml;nderungen und Erweiterungen nachreichen. Dabei geht es im Wesentlichen um die Benennung der Tabellenverkn&uuml;pfungen, die von dem Assistenten entweder initial angelegt oder aktualisiert werden sollen.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2025-05-07T12:10:48+00:00\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"27\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"SQL Server-Tabellenverkn&uuml;pfungsassistent, Teil 2\",\"datePublished\":\"2025-05-07T12:10:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\\\/\"},\"wordCount\":4560,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg01.met.vgwort.de\\\/na\\\/bf0487477047475db7cbade9e31158b0\",\"articleSection\":[\"2025\",\"3\\\/2025\",\"L\u00f6sungen\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\\\/\",\"name\":\"SQL Server-Tabellenverkn&uuml;pfungsassistent, Teil 2 - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg01.met.vgwort.de\\\/na\\\/bf0487477047475db7cbade9e31158b0\",\"datePublished\":\"2025-05-07T12:10:48+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg01.met.vgwort.de\\\/na\\\/bf0487477047475db7cbade9e31158b0\",\"contentUrl\":\"http:\\\/\\\/vg01.met.vgwort.de\\\/na\\\/bf0487477047475db7cbade9e31158b0\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"SQL Server-Tabellenverkn&uuml;pfungsassistent, Teil 2\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"SQL Server-Tabellenverkn&uuml;pfungsassistent, Teil 2 - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/","og_locale":"de_DE","og_type":"article","og_title":"SQL Server-Tabellenverkn&uuml;pfungsassistent, Teil 2","og_description":"Der SQL Server-Tabellenverkn&uuml;pfungsassistent, den wir im Beitrag \"SQL Server-Tabellenverkn&uuml;pfungsassistent\" (www.access-im-unternehmen.de\/1540) vorgestellt haben, funktioniert in vielen Settings bereits recht gut. Die generelle Praxistauglichkeit zeigt sichjedoch erst, wenn die Anwendung einmal auf andere Benutzer und\/oder Verwendungszwecke st&ouml;&szlig;t. Da dies nun geschehen ist, wollen wir im zweiten Teil der Beitragsreihe zum Thema SQL Server-Tabellenverkn&uuml;pfungsassistent einige &Auml;nderungen und Erweiterungen nachreichen. Dabei geht es im Wesentlichen um die Benennung der Tabellenverkn&uuml;pfungen, die von dem Assistenten entweder initial angelegt oder aktualisiert werden sollen.","og_url":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/","og_site_name":"Access im Unternehmen","article_published_time":"2025-05-07T12:10:48+00:00","author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"27\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"SQL Server-Tabellenverkn&uuml;pfungsassistent, Teil 2","datePublished":"2025-05-07T12:10:48+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/"},"wordCount":4560,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/#primaryimage"},"thumbnailUrl":"http:\/\/vg01.met.vgwort.de\/na\/bf0487477047475db7cbade9e31158b0","articleSection":["2025","3\/2025","L\u00f6sungen"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/","url":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/","name":"SQL Server-Tabellenverkn&uuml;pfungsassistent, Teil 2 - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/#primaryimage"},"thumbnailUrl":"http:\/\/vg01.met.vgwort.de\/na\/bf0487477047475db7cbade9e31158b0","datePublished":"2025-05-07T12:10:48+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/#primaryimage","url":"http:\/\/vg01.met.vgwort.de\/na\/bf0487477047475db7cbade9e31158b0","contentUrl":"http:\/\/vg01.met.vgwort.de\/na\/bf0487477047475db7cbade9e31158b0"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/SQL_ServerTabellenverknuepfungsassistent_Teil_2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"SQL Server-Tabellenverkn&uuml;pfungsassistent, Teil 2"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001551","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55001551"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001551\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001551"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001551"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001551"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}