{"id":55001252,"date":"2020-10-01T00:00:00","date_gmt":"2020-10-02T09:36:04","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1252"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Beziehungen_zwischen_TabellenAbfragen_ermitteln","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/","title":{"rendered":"Beziehungen zwischen Tabellen\/Abfragen ermitteln"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg07.met.vgwort.de\/na\/7e1191226eec4bf8aedddbb2ff126d09\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_05\/pic_1252_001.png\" alt=\"Datenmodell mit Beispielverkn&uuml;pfungen\" width=\"599,593\" height=\"510,0225\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Datenmodell mit Beispielverkn&uuml;pfungen<\/span><\/b><\/p>\n<p><b>Im Beitrag &#8222;Berichte und Unterberichte konfigurieren&#8220; haben wir die Aufgabe, f&uuml;r Kombinationen aus Tabellen und Abfragen herauszufinden, ob eine Beziehung zwischen den beiden Datenquellen besteht und &uuml;ber welche Felder diese realisiert wird. In diesem Fall nutzen wir dies, um automatisch die Verkn&uuml;pfungsfelder f&uuml;r die Datensatzquellen von Haupt- und Unterberichten zu ermitteln. Wir erhalten also die Tabelle\/Abfrage des Hauptberichts und des Unterberichts und ben&ouml;tigen nun die Felder, &uuml;ber welche die Beziehung zwischen den beiden Datenquellen hergestellt wird. Wie das gelingt, zeigt der vorliegende Beitrag.<\/b><\/p>\n<p>Als Beispiel f&uuml;r diesen Beitrag verwenden wir die Tabellen der S&uuml;dsturm-Datenbank, einen Ausschnitt des Datenmodells sehen Sie in Bild 1.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2020_05\/pic_1252_001.png\" alt=\"Datenmodell mit Beispielverkn&uuml;pfungen\" width=\"599,593\" height=\"510,0225\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Datenmodell mit Beispielverkn&uuml;pfungen<\/span><\/b><\/p>\n<p><b>Aufgabenstellung<\/b><\/p>\n<p>Wir ben&ouml;tigen eine Funktion, die f&uuml;r zwei gegebene Tabellen oder Abfragen die folgenden Daten herausfindet:<\/p>\n<ul>\n<li>Name der Parenttabelle<\/li>\n<li>Name des Parentfeldes<\/li>\n<li>Name der Childtabelle<\/li>\n<li>Name des Childfeldes<\/li>\n<\/ul>\n<p>Nochmal die Definition von Parent- und Childtabellen: Die Parenttabelle ist die Tabelle, deren Prim&auml;rschl&uuml;sselfeld an der Beziehung beteiligt ist, die Childtabelle ist die Tabelle, deren Fremdschl&uuml;sselfeld an der Beziehung beteiligt ist.<\/p>\n<p>Bei der Beziehung zwischen den Tabellen <b>tblKunden <\/b>und <b>tblBestellungen <\/b>ist also <b>tblKunden <\/b>die Parenttabelle und <b>tblBestellungen <\/b>die <b>Childtabelle<\/b>. Das Parentfeld hei&szlig;t <b>KundeID<\/b>, das Childfeld ebenfalls. Genau diese Informationen wollen wir mit der geplanten Funktion ermitteln.<\/p>\n<p><b>Definition der ben&ouml;tigten Funktion<\/b><\/p>\n<p>Die Funktion soll also die folgenden Eingangsparameter enthalten:<\/p>\n<ul>\n<li>Erste Tabelle (<b>strTableOrQuery1<\/b>)<\/li>\n<li>Zweite Tabelle (<b>strTableOrQuery2<\/b>)<\/li>\n<\/ul>\n<p>Au&szlig;erdem ben&ouml;tigen wir diese Ausgangsparameter f&uuml;r die Funktion:<\/p>\n<ul>\n<li>Parenttabelle (<b>strParenttable<\/b>)<\/li>\n<li>Parentfeld (<b>strParentfield<\/b>)<\/li>\n<li>Childtabelle (<b>strChildtable<\/b>)<\/li>\n<li>Childfeld (<b>strChildfield<\/b>)<\/li>\n<\/ul>\n<p>Schlie&szlig;lich soll die Funktion noch einen Funktionswert zur&uuml;ckliefern, der angibt, ob &uuml;berhaupt eine Beziehung gefunden wurde &#8211; dazu verwenden wir den Datentyp <b>Boolean<\/b>. Der Kopf der Funktion sieht also schon einmal so aus:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetReference(strTableOrQuery1<span style=\"color:blue;\"> As String<\/span>, strTableOrQuery2<span style=\"color:blue;\"> As String<\/span>, strParenttable<span style=\"color:blue;\"> As String<\/span>, strParentfield<span style=\"color:blue;\"> As String<\/span>, strChildtable<span style=\"color:blue;\"> As String<\/span>, strChildfield<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span><\/pre>\n<p>Den Rest der Funktion sehen Sie in Listing 1. Die Funktion stellt zun&auml;chst alle Werte der R&uuml;ckgabeparameter auf eine leere Zeichenkette ein (dies geschieht nur, weil wir mehrere Testaufrufe hintereinander durchf&uuml;hren und die Werte der Variablen in den Testaufrufen sonst beim erneutern Aufruf beibehalten w&uuml;rden).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetReference(strTableOrQuery1<span style=\"color:blue;\"> As String<\/span>, strTableOrQuery2<span style=\"color:blue;\"> As String<\/span>, strParenttable<span style=\"color:blue;\"> As String<\/span>, \r\n         strParentfield<span style=\"color:blue;\"> As String<\/span>, strChildtable<span style=\"color:blue;\"> As String<\/span>, strChildfield<span style=\"color:blue;\"> As String<\/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>rel<span style=\"color:blue;\"> As <\/span>DAO.Relation\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     strParenttable = \"\"\r\n     strParentfield = \"\"\r\n     strChildtable = \"\"\r\n     strChildfield = \"\"\r\n     For Each rel In db.Relations\r\n         <span style=\"color:blue;\">If <\/span>rel.Table = strTableOrQuery1 And rel.ForeignTable = strTableOrQuery2<span style=\"color:blue;\"> Then<\/span>\r\n             strParenttable = rel.Table\r\n             strChildtable = rel.ForeignTable\r\n             strParentfield = rel.Fields(0).Name\r\n             strChildfield = rel.Fields(0).ForeignName\r\n             GetReference = <span style=\"color:blue;\">True<\/span>\r\n             <span style=\"color:blue;\">Exit Function<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n         <span style=\"color:blue;\">If <\/span>rel.Table = strTableOrQuery2 And rel.ForeignTable = strTableOrQuery1<span style=\"color:blue;\"> Then<\/span>\r\n             strParenttable = rel.Table\r\n             strChildtable = rel.ForeignTable\r\n             strParentfield = rel.Fields(0).Name\r\n             strChildfield = rel.Fields(0).ForeignName\r\n             GetReference = <span style=\"color:blue;\">True<\/span>\r\n             <span style=\"color:blue;\">Exit Function<\/span>\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> rel\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: Funktion zum Ermitteln von Beziehungsdaten zweier Tabellen<\/span><\/b><\/p>\n<p>Dann durchl&auml;uft die Funktion alle <b>Relation<\/b>-Objekte der aktuellen Datenbank, die wir mit der <b>Relations<\/b>-Auflistung des <b>Database<\/b>-Objekts aus <b>CurrentDb <\/b>erhalten. In dieser <b>For Each<\/b>-Schleife pr&uuml;fen wir zun&auml;chst, ob der Name der mit <b>strTableOrQuery1 <\/b>&uuml;bergebenen Tabelle mit der Eigenschaft <b>Table <\/b>des <b>Relation<\/b>-Objekts &uuml;bereinstimmt und der Name aus <b>strTableOrQuery2 <\/b>mit dem Wert der Eigenschaft <b>ForeignTable<\/b>. <b>Table <\/b>enth&auml;lt immer den Namen der Parenttabelle, <b>ForeignTable <\/b>den Namen der Childtabelle.<\/p>\n<p>Ist das der Fall, f&uuml;llt die Funktion einfach die vier R&uuml;ckgabeparameter mit folgenden Eigenschaften des <b>Relation<\/b>-Objekts:<\/p>\n<ul>\n<li><b>strParenttable<\/b>: erh&auml;lt den Wert der Eigenschaft <b>Table<\/b><\/li>\n<li><b>strChildtable<\/b>: erh&auml;lt den Wert der Eigenschaft <b>ForeignTable<\/b><\/li>\n<li><b>strParentfield<\/b>: erh&auml;lt den Wert der Eigenschaft <b>Fields(0).Name<\/b><\/li>\n<li><b>strChildfield<\/b>: erh&auml;lt den Wert der Eigenschaft <b>Fields(0).ForeignName<\/b><\/li>\n<\/ul>\n<p>Warum <b>Fields(0)<\/b> Es kann sein, dass zwei Tabellen &uuml;ber mehr als eine Beziehung verkn&uuml;pft sind. Dieser Fall sollte aber in einem sauber formulierten Datenmodell nicht vorkommen, daher ber&uuml;cksichtigen wir nur eine Beziehung.<\/p>\n<p>Wenn die Parameter gef&uuml;llt sind, stellen wir noch den Funktionswert auf <b>True <\/b>ein und verlassen die Funktion mit <b>Exit Function<\/b>.<\/p>\n<p>Da es auch sein kann, dass die Parenttabelle mit dem Parameter <b>strTableOrQuery2 <\/b>und die Childtabelle mit dem Parameter <b>strTableOrQuery1 <\/b>&uuml;bergeben wurde, pr&uuml;fen wir in einer zweiten <b>If&#8230;Then<\/b>-Bedingung auch noch den umgekehrten Fall. Auch hier tragen wir dann die entsprechenden Werte in die R&uuml;ckgabeparameter ein und verlassen dann die Funktion.<\/p>\n<p><b>Testen der Funktion<\/b><\/p>\n<p>Um die Funktion zu testen, haben wir eine Prozedur mit einigen Testaufrufen programmiert. Diese finden Sie in gek&uuml;rzter Fassung in  Listing 2.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>Test_GetReference()\r\n     <span style=\"color:blue;\">Dim <\/span>strParenttable<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strParentfield<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strChildtable<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strChildfield<span style=\"color:blue;\"> As String<\/span>\r\n     If GetReference(\"tblArtikel\", \"tblBestelldetails\", strParenttable, strParentfield, strChildtable, strChildfield) _\r\n             = <span style=\"color:blue;\">True<\/span> Then\r\n         If <span style=\"color:blue;\">Not<\/span> (strParenttable = \"tblArtikel\" And strParentfield = \"ArtikelID\" _\r\n                 And strChildtable = \"tblBestelldetails\" And strChildfield = \"ArtikelID\") Then\r\n             <span style=\"color:blue;\">Debug.Print<\/span> \"Test 1a fehlgeschlagen 1\"\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">Debug.Print<\/span> \"Test 1a: fehlgeschlagen 2\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     If GetReference(\"tblBestelldetails\", \"tblArtikel\", strParenttable, strParentfield, strChildtable, strChildfield) _\r\n             = <span style=\"color:blue;\">True<\/span> Then\r\n         If <span style=\"color:blue;\">Not<\/span> (strParenttable = \"tblArtikel\" And strParentfield = \"ArtikelID\" _\r\n                 And strChildtable = \"tblBestelldetails\" And strChildfield = \"ArtikelID\") Then\r\n             <span style=\"color:blue;\">Debug.Print<\/span> \"Test 1b fehlgeschlagen 1\"\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         <span style=\"color:blue;\">Debug.Print<\/span> \"Test 1b: fehlgeschlagen 2\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     If GetReference(\"tblArtikel\", \"tblPersonal\", strParenttable, strParentfield, strChildtable, strChildfield) _\r\n             = <span style=\"color:blue;\">True<\/span> Then\r\n         <span style=\"color:blue;\">Debug.Print<\/span> \"Test 5 fehlgeschlagen\"\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 2: Testen der Funktion zum Ermitteln von Beziehungsdaten zweier Tabellen<\/span><\/b><\/p>\n<p><!--30percent--><\/p>\n<p>Diese Prozedur ruft die Funktion auf und &uuml;bergibt beliebige Kombinationen von Tabellen. Liefert die Funktion in diesen Aufrufen den Wert <b>True <\/b>zur&uuml;ck, pr&uuml;fen wir in einer <b>If&#8230;Then<\/b>-Bedingung, ob die vier R&uuml;ckgabeparameter die erwarteten Werte zur&uuml;ckliefern.<\/p>\n<p>Falls nicht, geben wir eine entsprechende Meldung im Direktbereich des VBA-Editors aus. Wenn schon das Funktionsergebnis entgegen den Erwartungen <b>False <\/b>lautet, geben wir ebenfalls eine Meldung im Direktbereich aus.<\/p>\n<p>Am Ende haben wir auch noch einen Test f&uuml;r die Kombination zweier Tabellen eingef&uuml;gt, f&uuml;r die es keine Beziehung gibt. Hier soll entsprechend der Wert <b>False <\/b>als Funktionswert zur&uuml;ckgegeben werden.<\/p>\n<p><b>Erweiterung auf Abfragen<\/b><\/p>\n<p>Die eingangs geschilderte Aufgabenstellung ist teilweise erledigt, allerdings kann es im Falle von Haupt- und Unterberichten (oder auch Haupt- und Unterformularen) auch einmal vorkommen, dass Abfragen statt Tabellen verwendet werden. Bei Abfragen basierend auf einer Tabelle, die nur zum Beschr&auml;nken der abzufragenden Felder oder zum Sortieren der Daten dient, k&ouml;nnen wir die oben beschriebene Funktion verwenden. Wenn die Abfragen jedoch mehr als eine Tabelle verwenden, wird es etwas aufwendiger, Beziehungen zwischen den Datensatzquellen von Haupt- und Unterbericht zu ermitteln.<\/p>\n<p>Hier m&uuml;ssen wir die Funktion also so erweitern, dass diese alle Tabellen der jeweiligen Abfrage untersucht und mit den Tabellen der anderen Abfrage abgleicht, um Beziehungen zu finden.<\/p>\n<p><b>Anzahl der Tabellen einer Datensatzquelle ermitteln<\/b><\/p>\n<p>F&uuml;r die folgenden Schritte wollen wir Tabellen und Abfragen gleich behandeln. In diesen Schritten wollen wir also herausfinden, ob es sich um eine einzelne Tabellen oder eine Abfrage mit einer oder mehreren Tabellen handelt. Den Entwurf einer Tabelle k&ouml;nnen wir mit dem der <b>TableDef<\/b>-Klasse untersuchen, den einer Abfrage mit der <b>QueryDef<\/b>-Klasse. Wie aber k&ouml;nnen wir Tabellen und Abfragen auf gleiche Weise untersuchen Mit dem <b>Recordset<\/b>-Objekt. Dieses untersuchen wir in einer Funktion namens <b>GetTables<\/b> (siehe Listing 3). Die Funktion hat keine andere Aufgabe als ein Array aller in einer Abfrage enthaltenen Tabellen zur&uuml;ckzuliefern. Deshalb verwendet sie neben dem Eingangsparameter <b>rst <\/b>den Ausgangsparameter <b>strTables <\/b>als <b>String<\/b>-Array.<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetTables(rst<span style=\"color:blue;\"> As <\/span>DAO.Recordset, strTables()<span style=\"color:blue;\"> As String<\/span>)\r\n     <span style=\"color:blue;\">Dim <\/span>fld<span style=\"color:blue;\"> As <\/span>DAO.Field\r\n     <span style=\"color:blue;\">Dim <\/span>strTable<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intTableCount<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>bolTableExists<span style=\"color:blue;\"> As Boolean<\/span>\r\n     For Each fld In rst.Fields\r\n         strTable = fld.SourceTable\r\n         On Error Resume <span style=\"color:blue;\">Next<\/span>\r\n         intTableCount = <span style=\"color:blue;\">UBound<\/span>(strTables) - <span style=\"color:blue;\">LBound<\/span>(strTables)\r\n         <span style=\"color:blue;\">On Error GoTo<\/span> 0\r\n         <span style=\"color:blue;\">If <\/span>intTableCount = 0<span style=\"color:blue;\"> Then<\/span>\r\n             bolTableExists = <span style=\"color:blue;\">False<\/span>\r\n         <span style=\"color:blue;\">Else<\/span>If intTableCount &gt; 0 Then\r\n             bolTableExists = <span style=\"color:blue;\">False<\/span>\r\n             For i = <span style=\"color:blue;\">LBound<\/span>(strTables) To <span style=\"color:blue;\">UBound<\/span>(strTables)\r\n                 <span style=\"color:blue;\">If <\/span>strTables(i) = strTable<span style=\"color:blue;\"> Then<\/span>\r\n                     bolTableExists = <span style=\"color:blue;\">True<\/span>\r\n                     <span style=\"color:blue;\">Exit For<\/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;\">End If<\/span>\r\n         <span style=\"color:blue;\">If <\/span>bolTableExists = <span style=\"color:blue;\">False<\/span><span style=\"color:blue;\"> Then<\/span>\r\n             intTableCount = intTableCount + 1\r\n             ReDim Preserve strTables(intTableCount)\r\n             strTables(intTableCount - 1) = strTable\r\n         <span style=\"color:blue;\">End If<\/span>\r\n     <span style=\"color:blue;\">Next<\/span> fld\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Funktion zum Einlesen aller Tabellen einer Abfrage in ein Array<\/span><\/b><\/p>\n<p>In einer <b>For Each<\/b>-Schleife durchl&auml;uft die Funktion alle <b>Field<\/b>-Elemente des Recordset-Objekts <b>rst<\/b>. Dabei speichert sie als Erstes den Namen der Tabelle, zu dem das Feld geh&ouml;rt, in der Variablen <b>strTable<\/b>. Diese Quelltabelle ermitteln wir mit der Eigenschaft <b>SourceTable <\/b>des <b>Field<\/b>-Objekts. Dann versuchen wir, die aktuelle Anzahl der Tabellen im Array <b>strTables <\/b>zu ermitteln, und zwar durch Subtraktion der Ergebnisse der Funktionen <b>UBound <\/b>und <b>LBound <\/b>des Arrays. Dies erledigen wir bei deaktivierter Fehlerbehandlung, denn diese w&uuml;rde einen Fehler liefern, wenn das Array noch keinen Eintrag enth&auml;lt. Ist <b>intTableCount <\/b>danach <b>0<\/b>, stellen wir die Variable <b>bolTableExists<\/b>, die schlicht angibt, ob die aktuelle Tabelle aus <b>strTable <\/b>bereits im Array enthalten ist &#8211; und wenn dieses noch keinen Eintrag hat, ist das definitiv noch nicht der Fall.<\/p>\n<p>Ist <b>intTableCount <\/b>nicht <b>0<\/b>, m&uuml;ssen wir genauer pr&uuml;fen, ob die Tabelle aus <b>strTable <\/b>schon im Array enthalten ist, denn wir pr&uuml;fen dies ja f&uuml;r jedes Feld der Abfrage, und es kann vorkommen, das mehr als ein Feld zur gleichen Tabelle geh&ouml;rt.<\/p>\n<p>Also durchlaufen wir in diesem Fall in einer <b>For&#8230;Next<\/b>-Schleife alle Elemente des Arrays. Dabei pr&uuml;fen wir, ob der aktuelle Wert des Arrays gleich dem Inhalt von <b>strTable <\/b>ist. Ist das der Fall, existiert die Tabelle bereits im Array und wir stellen <b>bolTableExists <\/b>auf <b>True <\/b>ein und verlassen die Schleife. Ist die Tabelle nicht im Array vorhanden, verlassen wir die Schleife und <b>bolTableExists <\/b>beh&auml;lt den Wert <b>False<\/b>.<\/p>\n<p>Diesen pr&uuml;fen wir in der folgenden <b>If&#8230;Then<\/b>-Bedingung. Hat <b>bolTableExists <\/b>den Wert <b>False<\/b>, erh&ouml;hen wir <b>intTableCount <\/b>um eins, erweitern das Array auf den Wert von <b>intTableCount <\/b>und weisen dem Element mit dem neuen Index den Wert von <b>strTable <\/b>zu. Nachdem wir auf diese Weise alle Felder durchlaufen haben, ist das Array <b>strTables <\/b>mit allen Tabellen der Abfrage gef&uuml;llt und wir k&ouml;nnen die Prozedur verlassen. Danach passen wir noch die Funktion <b>GetReference <\/b>so an, dass diese nicht nur f&uuml;r Tabellen funktioniert, sondern auch f&uuml;r Abfragen, die eine oder mehrere Tabellen enthalten (siehe Listing 4).<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetReference(strTableOrQuery1<span style=\"color:blue;\"> As String<\/span>, strTableOrQuery2<span style=\"color:blue;\"> As String<\/span>, strParenttable<span style=\"color:blue;\"> As String<\/span>, _\r\n         strParentfield<span style=\"color:blue;\"> As String<\/span>, strChildtable<span style=\"color:blue;\"> As String<\/span>, strChildfield<span style=\"color:blue;\"> As String<\/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>rst1<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>rst2<span style=\"color:blue;\"> As <\/span>DAO.Recordset\r\n     <span style=\"color:blue;\">Dim <\/span>rel<span style=\"color:blue;\"> As <\/span>DAO.Relation\r\n     <span style=\"color:blue;\">Dim <\/span>strTables1()<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strTables2()<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strTable1<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>strTable2<span style=\"color:blue;\"> As String<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intTable1<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>intTable2<span style=\"color:blue;\"> As Integer<\/span>\r\n     <span style=\"color:blue;\">Set<\/span> db = CurrentDb\r\n     strParenttable = \"\"\r\n     strParentfield = \"\"\r\n     strChildtable = \"\"\r\n     strChildfield = \"\"\r\n     <span style=\"color:blue;\">Set<\/span> rst1 = db.OpenRecordset(\"SELECT TOP 1 * FROM (\" & strTableOrQuery1 & \")\", dbOpenSnapShot)\r\n     <span style=\"color:blue;\">Set<\/span> rst2 = db.OpenRecordset(\"SELECT TOP 1 * FROM (\" & strTableOrQuery2 & \")\", dbOpenSnapShot)\r\n     GetTables rst1, strTables1\r\n     GetTables rst2, strTables2\r\n     For intTable1 = <span style=\"color:blue;\">LBound<\/span>(strTables1) To <span style=\"color:blue;\">UBound<\/span>(strTables1)\r\n         For intTable2 = <span style=\"color:blue;\">LBound<\/span>(strTables2) To <span style=\"color:blue;\">UBound<\/span>(strTables2)\r\n             For Each rel In db.Relations\r\n                 strTable1 = strTables1(intTable1)\r\n                 strTable2 = strTables2(intTable2)\r\n                 If (rel.Table = strTable1 And rel.ForeignTable = strTable2) Or (rel.Table = strTable2 _\r\n                         And rel.ForeignTable = strTable1) Then\r\n                     strParenttable = rel.Table\r\n                     strChildtable = rel.ForeignTable\r\n                     strParentfield = rel.Fields(0).Name\r\n                     strChildfield = rel.Fields(0).ForeignName\r\n                     GetReference = <span style=\"color:blue;\">True<\/span>\r\n                     <span style=\"color:blue;\">Exit Function<\/span>\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n             <span style=\"color:blue;\">Next<\/span> rel\r\n         <span style=\"color:blue;\">Next<\/span> intTable2\r\n     <span style=\"color:blue;\">Next<\/span> intTable1\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Tabellen und beteiligte Felder einer Beziehung ermitteln<\/span><\/b><\/p>\n<p>Die Funktion nimmt die gleichen Parameter entgegen wie zuvor. Sie verwendet allerdings weitere Variablen, zum Beispiel die beiden Arrays <b>strTables1 <\/b>und <b>strTables2<\/b>, welche die Namen der Tabelle oder der Tabellen (falls eine Abfrage mit <b>strTableOrQuery1 <\/b>und <b>strTableOrQuery2 <\/b>&uuml;bergeben wurde). Auch die Recordset-Variablen <b>rst1 <\/b>und <b>rst2 <\/b>sind neu sowie die Variablen <b>strTable1<\/b>, <b>strTable2<\/b>, <b>intTable1 <\/b>und <b>intTable2<\/b>.<\/p>\n<p>Wir erstellen ein Recordset namens <b>rst1 <\/b>auf Basis der mit <b>strTableOrQuery1 <\/b>&uuml;bergebenen Tabelle oder Abfrage, analog f&uuml;r <b>rst2 <\/b>und <b>strTableOrQuery2<\/b>. <\/p>\n<p>Dann ruft die Funktion f&uuml;r beide Recordsets die <b>Funktion GetTables <\/b>auf, um die am Recordset beteiligten Tabellen jeweils in einem Array zur&uuml;ckzuliefern. Um den eigentlichen Kern der Prozedur herum f&uuml;gen wir nun zwei verschachtelte Schleifen hinzu. Die &auml;u&szlig;ere durchl&auml;uft alle Elemente des Arrays <b>strTables1<\/b>, die innere alle Elemente des Arrays <b>strTables2<\/b>. Innerhalb der Schleifen weisen wir den Variablen <b>strTable1 <\/b>und <b>strTable2 <\/b>die jeweils aktuellen Elemente der Arrays <b>strTables1 <\/b>und <b>strTables2 <\/b>hinzu und f&uuml;hren dann die Schritte aus, die wir auch in der vorherigen Version der Funktion <b>GetReference <\/b>erledigt haben.<\/p>\n<p><b>Testen der Suche von Beziehungen in verkn&uuml;pften Abfragen<\/b><\/p>\n<p>Damit brauchen wir nur noch einige Abfragen zum Testen der neu hinzugekommenen Funktionalit&auml;t zu erstellen und neue Testf&auml;lle zur Prozedur Test_GetReference hinzuzuf&uuml;gen. Der Vorteil der Nutzung unserer Testprozedur ist: Die &Auml;nderungen der Funktion <b>GetReference <\/b>k&ouml;nnen wir f&uuml;r die bereits vorhandenen F&auml;lle ganz einfach durch einen erneuten Aufruf der Testprozedur testen. Wenn keine Fehlermeldungen im Direktfenster auftauchen, liefert die Funktion auch nach der &Auml;nderung noch die erwarteten Ergebnisse.<\/p>\n<p>Um die neuen Funktionen zu testen, legen wir also zwei Abfragen an: die erste enth&auml;lt die beiden Tabellen <b>tblArtikel <\/b>und <b>tblKategorien<\/b>, die zweite die beiden Tabellen <b>tblBestellungen <\/b>und <b>tblBestelldetails<\/b>. Wichtig ist nat&uuml;rlich, dass das Prim&auml;rschl&uuml;sselfeld und das Fremdschl&uuml;sselfeld der beiden Tabellen, &uuml;ber welche die Beziehung zwischen den beiden Abfragen hergestellt wird, im Abfrageergebnis erscheinen &#8211; hier also das Feld <b>ArtikelID <\/b>der beiden Tabellen <b>tblBestelldetails <\/b>und <b>tblArtikel<\/b>.<\/p>\n<p>Mit dem neuen Testfall (siehe Listing 5) k&ouml;nnen wir nun auch die an einer Beziehung zwischen zwei Abfragen beteiligten Felder ermitteln.<\/p>\n<pre>If GetReference(\"qryBestelldetailsBestellungen\", \"qryArtikelKategorien\", strParenttable, strParentfield, _\r\n         strChildtable, strChildfield) = <span style=\"color:blue;\">True<\/span> Then\r\n     If <span style=\"color:blue;\">Not<\/span> (strParenttable = \"tblArtikel\" And strParentfield = \"ArtikelID\" And strChildtable = \"tblBestelldetails\" _\r\n             And strChildfield = \"ArtikelID\") Then\r\n         <span style=\"color:blue;\">Debug.Print<\/span> \"Test 6 fehlgeschlagen 1\"\r\n     <span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">Else<\/span>\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"Test 6: fehlgeschlagen 2\"\r\n<span style=\"color:blue;\">End If<\/span>\r\n<span style=\"color:blue;\">If <\/span>GetReference(\"tblArtikel\", \"tblPersonal\", strParenttable, strParentfield, strChildtable, strChildfield) = <span style=\"color:blue;\">True<\/span><span style=\"color:blue;\"> Then<\/span>\r\n     <span style=\"color:blue;\">Debug.Print<\/span> \"Test 5 fehlgeschlagen\"\r\n<span style=\"color:blue;\">End If<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Neuer Testfall f&uuml;r das Ermitteln von Verkn&uuml;pfungsfeldern zwischen zwei Abfragen<\/span><\/b><\/p>\n<p><b>Erweiterung f&uuml;r mehrere Beziehungen<\/b><\/p>\n<p>Wir haben noch eine weitere Version der Funktion <b>GetReference <\/b>erstellt, die wir <b>GetReferences<\/b> genannt haben. Diese erlaubt die Behandlung des eher seltenen Falls von mehreren Beziehungen zwischen zwei Tabellen oder den Tabellen zweier Abfragen.<\/p>\n<p>Diese Funktion verwendet Arrays f&uuml;r die R&uuml;ckgabe der Tabellen und Felder der Beziehungen (siehe Listing 6). Diese k&ouml;nnen nun nicht mehr geleert werden, indem man sie einfach auf eine leere Zeichenkette einstellt. Stattdessen leeren wir diese mit der <b>Erase<\/b>-Funktion. Wenn die Funktion innerhalb der beiden Schleifen eine Beziehung findet, werden die Arrays mit <b>Redim Preserve <\/b>um einen Eintrag erweitert und die neuen Daten werden f&uuml;r den Eintrag mit dem entsprechenden Index hinzugef&uuml;gt. Der Test beziehungsweise der Aufruf &auml;ndert sich entsprechend:<\/p>\n<pre><span style=\"color:blue;\">Public Function <\/span>GetReferences(strTableOrQuery1<span style=\"color:blue;\"> As String<\/span>, strTableOrQuery2<span style=\"color:blue;\"> As String<\/span>, strParenttables()<span style=\"color:blue;\"> As String<\/span>, _\r\n         strParentfields()<span style=\"color:blue;\"> As String<\/span>, strChildtables()<span style=\"color:blue;\"> As String<\/span>, strChildfields()<span style=\"color:blue;\"> As String<\/span>)<span style=\"color:blue;\"> As Boolean<\/span>\r\n     ...\r\n     Erase strParenttables\r\n     Erase strParentfields\r\n     Erase strChildtables\r\n     Erase strChildfields\r\n     For intTable1 = <span style=\"color:blue;\">LBound<\/span>(strTables1) To <span style=\"color:blue;\">UBound<\/span>(strTables1)\r\n         For intTable2 = <span style=\"color:blue;\">LBound<\/span>(strTables2) To <span style=\"color:blue;\">UBound<\/span>(strTables2)\r\n             For Each rel In db.Relations\r\n                 strTable1 = strTables1(intTable1)\r\n                 strTable2 = strTables2(intTable2)\r\n                 If (rel.Table = strTable1 And rel.ForeignTable = strTable2) Or (rel.Table = strTable2 _\r\n                         And rel.ForeignTable = strTable1) Then\r\n                     intRelations = intRelations + 1\r\n                     ReDim Preserve strParenttables(intRelations)\r\n                     ReDim Preserve strChildtables(intRelations)\r\n                     ReDim Preserve strParentfields(intRelations)\r\n                     ReDim Preserve strChildfields(intRelations)\r\n                     strParenttables(intRelations - 1) = rel.Table\r\n                     strChildtables(intRelations - 1) = rel.ForeignTable\r\n                     strParentfields(intRelations - 1) = rel.Fields(0).Name\r\n                     strChildfields(intRelations - 1) = rel.Fields(0).ForeignName\r\n                     GetReferences = <span style=\"color:blue;\">True<\/span>\r\n                 <span style=\"color:blue;\">End If<\/span>\r\n             <span style=\"color:blue;\">Next<\/span> rel\r\n         <span style=\"color:blue;\">Next<\/span> intTable2\r\n     <span style=\"color:blue;\">Next<\/span> intTable1\r\n<span style=\"color:blue;\">End Function<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Funktion zum Ermitteln mehrerer Beziehungen zwischen zwei Datensatzquellen<\/span><\/b><\/p>\n<pre><span style=\"color:blue;\">If <\/span>GetReferences(\"qryKundenPersonal\",  \"tblBestellungen\", strParenttables, strParentfields,  strChildtables, strChildfields) = <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> (strParenttables(0) = \"tblKunden\" And  strParentfields(0) = \"KundeID\" And strChildtables(0)  = \"tblBestellungen\" And strChildfields(0) = \"KundeID\") <span style=\"color:blue;\"> Then<\/span><\/pre>\n<p>Um alle gefundenen Beziehungen zu ermitteln, durchlaufen Sie die Arrays in einer Schleife. Wie das gelingt, zeigen wir im Beitrag <b>Berichte und Unterberichte konfigurieren <\/b>(<b>www.access-im-unternehmen.de\/****<\/b>), wo wir davon ausgehen, dass auch einmal mehrere Beziehungen zwischen zwei Datensatzquellen vorliegen.<\/p>\n<p><b>Zusammenfassung und Ausblick<\/b><\/p>\n<p>Dieser Beitrag zeigt, wie Sie die an einer Beziehung zwischen zwei Tabellen oder Abfragen beteiligten Felder ermitteln k&ouml;nnen. Dies ist in unserem Fall notwendig f&uuml;r eine Anwendung, die das F&uuml;llen von Unterberichten zur Laufzeit erm&ouml;glicht &#8211; hier sollen bei der Konfiguration automatisch die an der Beziehung der Datensatzquellen von Haupt- und Unterbericht beteiligten Felder ermittelt werden.<\/p>\n<p>Au&szlig;erdem lernen Sie hier ein paar selten genutzte Elemente von DAO kennen &#8211; zum Beispiel das Relation-Objekt oder auch die Eigenschaften, mit denen man die Basistabelle von Feldern in Abfragen ermitteln kann. <\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>VerknuepfungenZwischenTabellenUndAbfragen.accdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/A95E0268-6D42-452D-B267-CE967238D865\/aiu_1252.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Im Beitrag &#8222;Berichte und Unterberichte konfigurieren&#8220; haben wir die Aufgabe, f&uuml;r Kombinationen aus Tabellen und Abfragen herauszufinden, ob eine Beziehung zwischen den beiden Datenquellen besteht und &uuml;ber welche Felder diese realisiert wird. In diesem Fall nutzen wir dies, um automatisch die Verkn&uuml;pfungsfelder f&uuml;r die Datensatzquellen von Haupt- und Unterberichten zu ermitteln. Wir erhalten also die Tabelle\/Abfrage des Hauptberichts und des Unterberichts und ben&ouml;tigen nun die Felder, &uuml;ber welche die Beziehung zwischen den beiden Datenquellen hergestellt wird. Wie das gelingt, zeigt der vorliegende Beitrag.<\/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":[662020,66052020,44000021],"tags":[],"class_list":["post-55001252","post","type-post","status-publish","format-standard","hentry","category-662020","category-66052020","category-Tabellen_und_Datenmodellierung"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Beziehungen zwischen Tabellen\/Abfragen ermitteln - 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\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Beziehungen zwischen Tabellen\/Abfragen ermitteln\" \/>\n<meta property=\"og:description\" content=\"Im Beitrag &quot;Berichte und Unterberichte konfigurieren&quot; haben wir die Aufgabe, f&uuml;r Kombinationen aus Tabellen und Abfragen herauszufinden, ob eine Beziehung zwischen den beiden Datenquellen besteht und &uuml;ber welche Felder diese realisiert wird. In diesem Fall nutzen wir dies, um automatisch die Verkn&uuml;pfungsfelder f&uuml;r die Datensatzquellen von Haupt- und Unterberichten zu ermitteln. Wir erhalten also die Tabelle\/Abfrage des Hauptberichts und des Unterberichts und ben&ouml;tigen nun die Felder, &uuml;ber welche die Beziehung zwischen den beiden Datenquellen hergestellt wird. Wie das gelingt, zeigt der vorliegende Beitrag.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-10-02T09:36:04+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg07.met.vgwort.de\/na\/7e1191226eec4bf8aedddbb2ff126d09\" \/>\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=\"14\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Beziehungen zwischen Tabellen\\\/Abfragen ermitteln\",\"datePublished\":\"2020-10-02T09:36:04+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\\\/\"},\"wordCount\":2057,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/7e1191226eec4bf8aedddbb2ff126d09\",\"articleSection\":[\"2020\",\"5\\\/2020\",\"Tabellen und Datenmodellierung\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\\\/\",\"name\":\"Beziehungen zwischen Tabellen\\\/Abfragen ermitteln - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/7e1191226eec4bf8aedddbb2ff126d09\",\"datePublished\":\"2020-10-02T09:36:04+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/7e1191226eec4bf8aedddbb2ff126d09\",\"contentUrl\":\"http:\\\/\\\/vg07.met.vgwort.de\\\/na\\\/7e1191226eec4bf8aedddbb2ff126d09\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Beziehungen zwischen Tabellen\\\/Abfragen ermitteln\"}]},{\"@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":"Beziehungen zwischen Tabellen\/Abfragen ermitteln - 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\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/","og_locale":"de_DE","og_type":"article","og_title":"Beziehungen zwischen Tabellen\/Abfragen ermitteln","og_description":"Im Beitrag \"Berichte und Unterberichte konfigurieren\" haben wir die Aufgabe, f&uuml;r Kombinationen aus Tabellen und Abfragen herauszufinden, ob eine Beziehung zwischen den beiden Datenquellen besteht und &uuml;ber welche Felder diese realisiert wird. In diesem Fall nutzen wir dies, um automatisch die Verkn&uuml;pfungsfelder f&uuml;r die Datensatzquellen von Haupt- und Unterberichten zu ermitteln. Wir erhalten also die Tabelle\/Abfrage des Hauptberichts und des Unterberichts und ben&ouml;tigen nun die Felder, &uuml;ber welche die Beziehung zwischen den beiden Datenquellen hergestellt wird. Wie das gelingt, zeigt der vorliegende Beitrag.","og_url":"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-10-02T09:36:04+00:00","og_image":[{"url":"http:\/\/vg07.met.vgwort.de\/na\/7e1191226eec4bf8aedddbb2ff126d09","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"14\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Beziehungen zwischen Tabellen\/Abfragen ermitteln","datePublished":"2020-10-02T09:36:04+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/"},"wordCount":2057,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/7e1191226eec4bf8aedddbb2ff126d09","articleSection":["2020","5\/2020","Tabellen und Datenmodellierung"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/","url":"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/","name":"Beziehungen zwischen Tabellen\/Abfragen ermitteln - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/#primaryimage"},"thumbnailUrl":"http:\/\/vg07.met.vgwort.de\/na\/7e1191226eec4bf8aedddbb2ff126d09","datePublished":"2020-10-02T09:36:04+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/#primaryimage","url":"http:\/\/vg07.met.vgwort.de\/na\/7e1191226eec4bf8aedddbb2ff126d09","contentUrl":"http:\/\/vg07.met.vgwort.de\/na\/7e1191226eec4bf8aedddbb2ff126d09"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Beziehungen_zwischen_TabellenAbfragen_ermitteln\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Beziehungen zwischen Tabellen\/Abfragen ermitteln"}]},{"@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\/55001252","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=55001252"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001252\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001252"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001252"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001252"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}