{"id":55000619,"date":"2008-08-01T00:00:00","date_gmt":"2021-02-11T21:21:49","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=619"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Suchfunktionen_von_einfach_bis_komplex","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/","title":{"rendered":"Suchfunktionen von einfach bis komplex"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg03.met.vgwort.de\/na\/0657af7ab58247838072c8162700a132\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Eine einfache Suchfunktion ist schnell gebaut. Ein Suchfeld einrichten, eine Schaltfl&auml;che mit dem notwendigen VBA-Code anlegen und schlie&szlig;lich ein Steuerelement zum Anzeigen des Suchergebnisses. Was aber, wenn es nicht nur eines, sondern viele Kriterien gibt, und diese sich auch noch &uuml;ber mehrere Tabellen erstrecken Dieser Beitrag diskutiert die M&ouml;glichkeiten und zeigt einen Ansatz, mit dem Sie auf jeden Fall den &Uuml;berblick behalten &#8211; egal, wie viele Kriterien und Tabellen die Suche umfasst.<\/b><\/p>\n<p>Wer Daten in einer Datenbank speichert, will diese meist auch nach verschiedenen Kriterien durchsuchen. Oftmals reichen wenige Suchmerkmale: Wer beispielsweise einen Shop betreibt, braucht in der Regel nur die Kundennummer, um dann zu einer angefragten Bestellung zu gelangen. Dies erledigt ein kleines Suchfeld zur Eingabe eben dieser Nummer. Die Abfrage, die aus den Kundendatens&auml;tzen den passenden heraussucht, ist ebenso einfach und die gr&ouml;&szlig;te Herausforderung d&uuml;rfte schon sein, sich f&uuml;r ein Listenfeld oder ein Unterformular zur Anzeige der gefundenen Kundendaten zu entscheiden.<\/p>\n<p><b>Viele Felder<\/b><\/p>\n<p>Etwas umfangreicher wird es, wenn sich der Suchbegriff nicht nur auf eines, sondern auf mehrere Tabellenfelder bezieht. Dies &auml;ndert im Vergleich zum ersten Beispiel nicht viel; Sie m&uuml;ssen lediglich die Abfrage um einige Kriterien erweitern.<\/p>\n<p class=\"zwischen-berschrift-oberer-spaltenrand\">Tabelle mit Lookup-Feldern<\/p>\n<p>Lookup-Felder zeigen in Lookup-Tabellen ausgelagerte Informationen an. Einfachstes Beispiel ist die Anrede, die oft in der eigentlichen Tabelle als Fremdschl&uuml;sselfeld angelegt ist und auf eine weitere Tabelle namens <b>tblAnreden <\/b>verweist, in der die eigentlichen Begriffe wie <b>Herr <\/b>oder <b>Frau <\/b>stehen.<\/p>\n<p>Das Durchsuchen von Tabellen mit Lookup-Feldern ist ebenfalls kein Hexenwerk: Man verwendet dann einfach eine Abfrage, welche die ben&ouml;tigten Felder der Lookup-Tabellen einbindet, und legt die Kriterien f&uuml;r diese Felder genau wie f&uuml;r die &uuml;brigen Felder dieser Tabelle fest.<\/p>\n<p><b>Viele Tabellen<\/b><\/p>\n<p>Richtig interessant wird es, wenn eine Tabelle viele verkn&uuml;pfte Tabellen besitzt, die je nach Art der Information per 1:n- oder auch per m:n-Beziehung angebunden sind. Ein passendes Beispiel ist eine Dokumentenverwaltung.<\/p>\n<p>Diese besteht nicht nur aus der Tabelle mit den Dokumenten selbst, sondern aus vielen weiteren Informationen, die sich teils in per 1:n-Beziehung verkn&uuml;pften Tabellen (zum Beispiel Dokumentart oder Versionen) oder auch in Tabellen befinden, die durch eine m:n-Beziehung angebunden sind (Autoren, Kategorien, Stichw&ouml;rter). Mitunter befinden sich die interessanten Felder dort sogar in den Verkn&uuml;pfungstabellen zur Realisierung der m:n-Beziehung. Das Datenmodell des Beispiels k&ouml;nnen Sie Bild 1 entnehmen.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic001_opt.jpeg\" alt=\"pic001.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 1: Datenmodell der Beispieldatenbank<\/span><\/b><\/p>\n<p class=\"zwischen-berschrift-oberer-spaltenrand\">Eine gro&szlig;e Abfrage<\/p>\n<p>Prinzipiell k&ouml;nnte man eine gro&szlig;e Abfrage erstellen, die alle potenziell f&uuml;r die Suche relevanten Tabellen enth&auml;lt und dabei die im Datenmodell festgelegten <b>INNER JOIN<\/b>s, also die Verkn&uuml;pfungen zwischen den Tabellen, beibeh&auml;lt. Diese w&uuml;rde man dann in Abh&auml;ngigkeit von den im Suchfenster gew&auml;hlten Kriterien mit einer entsprechenden <b>WHERE<\/b>-Klausel ausstatten. Grunds&auml;tzlich ist das die einfachste Methode. Allerdings muss man mehrere Faktoren ber&uuml;cksichtigen:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Je mehr Tabellen die Abfrage enth&auml;lt, desto mehr <b>JOIN<\/b>s sind vorhanden. Dies bedeutet eine entsprechend geringe Performance.<\/li>\n<li class=\"aufz-hlung\">Wenn sie die <b>INNER JOIN<\/b>s vom Datenmodell &uuml;bernehmen und tats&auml;chlich alle Tabellen in die Abfrage integrieren, m&uuml;ssen Sie sich bewusst sein, dass auch f&uuml;r alle verkn&uuml;pften Tabellen Daten zu einem Datensatz der Haupttabelle vorhanden sein muss.<\/li>\n<li class=\"aufz-hlung\">Ist das nicht der Fall, also wenn es wie im hier vorgestellten Beispiel auch Elemente in der Haupttabelle (<b>tblDokumente<\/b>) gibt, f&uuml;r die mindestens eine verkn&uuml;pfte Tabelle (zum Beispiel <b>tblDokumenteStichwoerter<\/b>) keine Daten enth&auml;lt, dann werden diese Dokumente im Abfrageergebnis auch nicht angezeigt.<\/li>\n<\/ul>\n<p>Dies k&ouml;nnen Sie am Beispiel der Abfrage aus Bild 2 pr&uuml;fen. Wenn die Tabelle <b>tblDokumente <\/b>zwei Datens&auml;tze enth&auml;lt, von denen lediglich einer mit Eintr&auml;gen der Tabelle <b>tblDokumenteAttribute <\/b>verkn&uuml;pft ist, dann liefert die Abfrage auch nur den oder die verkn&uuml;pften Datens&auml;tze zur&uuml;ck.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic002_opt.jpeg\" alt=\"pic002.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 2: Beispielabfrage mit per m:n-Beziehung verkn&uuml;pften Tabellen<\/span><\/b><\/p>\n<p>Prinzipiell ist ein <b>INNER JOIN <\/b>also auch ein Kriterium, auch wenn man es nicht an der Stelle festlegt, an der man &uuml;blicherweise die Kriterien eintr&auml;gt, also in der Zeile <b>Kriterien <\/b>des Abfrageentwurfs.<\/p>\n<p>Wenn man dies auf eine gro&szlig;e Abfrage &uuml;bertr&auml;gt, die alle verkn&uuml;pften Tabellen enth&auml;lt, m&uuml;sste ein Dokument zun&auml;chst einmal Eintr&auml;ge in allen verkn&uuml;pften Tabellen aufweisen, um &uuml;berhaupt im Ergebnis einer solchen Abfrage aufzutauchen. Sobald es entweder keine Stichw&ouml;rter (<b>tblDokumenteStichwoerter<\/b>), Kategorien (<b>tblDokumenteKategorien<\/b>), Autoren (<b>tblDokumenteAutoren<\/b>) oder sonstige Attribute aufweist (<b>tblDokumenteAttribute<\/b>), zeigt die Abfrage ein Dokument auch nicht an &#8211; unabh&auml;ngig von weiteren hinzugef&uuml;gten Kriterien.<\/p>\n<p><b>LEFT JOIN statt INNER JOIN<\/b><\/p>\n<p>Wie nun kann man eine Abfrage mit verkn&uuml;pften Tabellen verwenden, ohne dass nicht vorhandene Daten in einer der verkn&uuml;pften Tabellen direkt das K.O.-Kriterium f&uuml;r einen Dokumentdatensatz bedeuten Probieren wir es aus und stellen schnell eine passende Abfrage zusammen, indem wir die f&uuml;nf Tabellen <b>tblDokumente<\/b>, <b>tblAutoren<\/b>, <b>tblKategorien<\/b>, <b>tblDokumenteAutoren <\/b>sowie <b>tblDokumenteKategorien <\/b>in den Abfrageentwurf ziehen und die Felder <b>ID<\/b>, <b>Pfad <\/b>und <b>Dateiname <\/b>der Tabelle <b>tblDokumente <\/b>sowie <b>Kategorie <\/b>aus <b>tblKategorien <\/b>und <b>NameAutor <\/b>aus <b>tblAutoren <\/b>im Raster der anzuzeigenden Felder unterbringen (siehe Bild 3).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic003_opt.jpeg\" alt=\"pic003.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 3: Entwurfsansicht einer Abfrage mit einer Tabelle, die mit zwei anderen Tabellen per m:n-Beziehung verkn&uuml;pft ist<\/span><\/b><\/p>\n<p>Ein schneller Wechsel in die Datenblattansicht sollte zumindest einen Datensatz anzeigen, denn die Datenbank enth&auml;lt bereits einige Datens&auml;tze, von denen zumindest einer mit allen per m:n-Beziehung verkn&uuml;pften Tabellen verbunden ist. Aber weit gefehlt: Dort erscheint kein einziger Datensatz. Das liegt daran, dass Access beim Anlegen der Beziehungen im Abfrageentwurf ein wenig zu eifrig war: Es hat n&auml;mlich Beziehungen zwischen den Feldern <b>ID <\/b>der Tabellen <b>tblDokumente <\/b>und <b>tblAutoren<\/b>, <b>tblDokumente <\/b>und <b>tblKategorien <\/b>sowie <b>tblDokumenteAutoren <\/b>und <b>tblDokumenteKategorien <\/b>angelegt. Schuld war die Option <b>Autoverkn&uuml;pfung aktivieren<\/b>, die Sie aber ausschalten k&ouml;nnen. Ohne diese ist der Abfrageentwurf gleich ein wenig &uuml;berschaubarer, wie Bild 4 zeigt, und au&szlig;erdem blendet das Ergebnis auch einige Datens&auml;tze ein (siehe Bild 5).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic004_opt.jpeg\" alt=\"pic004.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 4: Ohne zus&auml;tzliche Beziehungen klappt es auch mit den Verkn&uuml;pfungen.<\/span><\/b><\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic005_opt.jpeg\" alt=\"pic005.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 5: Ohne zus&auml;tzliche Beziehungen klappt es besser mit den Verkn&uuml;pfungen.<\/span><\/b><\/p>\n<p>Betrachten wie diese Abfrage nun stellvertretend f&uuml;r eine viel umfangreichere Abfrage, die alle Tabellen des Beispieldatenmodells enth&auml;lt. Das Ziel w&auml;re nun, die Daten mit dieser Abfrage nach nur einem Kriterium wie etwa dem Autor zu durchsuchen und alle passenden Dokumente zu ermitteln, auch wenn diese nicht mit einem Datensatz der Tabelle <b>tblKategorien <\/b>verkn&uuml;pft sind.<\/p>\n<p>Ein Ansatz w&auml;re, statt eines <b>INNER JOIN<\/b> ein <b>OUTER JOIN <\/b>zu verwenden, das daf&uuml;r sorgt, dass die Abfrage nicht nur die Datens&auml;tze ermittelt, die &uuml;ber alle enthaltenen Tabellen verteilt sind, sondern f&uuml;r alle Datens&auml;tze der Tabelle <b>tblDokumente <\/b>mindestens einen Eintrag ausgibt, auch wenn diese nicht mit der Autoren- und der Kategorientabelle verkn&uuml;pft sind.<\/p>\n<p>Fangen wir einfach an und versuchen die <b>INNER JOIN<\/b>-Methode zun&auml;chst nur mit den Tabellen <b>tblDokumente<\/b>, <b>tblDokumenteAutoren <\/b>und <b>tblDokumenteKategorien <\/b>(siehe Bild 6). Dies funktioniert ohne Probleme: Die Abfrage zeigt etwas mehr als die in der Tabelle <b>tblDokumente <\/b>enthaltenen Datens&auml;tze an, was daraus resultiert, dass einige Dokumente mit mehreren Eintr&auml;gen der Tabellen <b>tblDokumenteAutoren <\/b>und <b>tblDokumenteKategorien <\/b>verkn&uuml;pft sind.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic006_opt.jpeg\" alt=\"pic006.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 6: Die Tabelle tblDokumente ist &uuml;ber zwei OUTER JOINs mit den Tabellen tblDokumenteKategorien und tblAutoren verkn&uuml;pft.<\/span><\/b><\/p>\n<p>Jetzt wird es interessant: Wir f&uuml;gen die Tabellen <b>tblAutoren <\/b>und <b>tblKategorien <\/b>hinzu, denn immerhin sollen die Felder <b>NameAutor <\/b>und <b>Kategorie <\/b>gegebenenfalls als Suchkriterien zum Einsatz kommen. Doch der Versuch scheitert: Die Abfrage enth&auml;lt mehrdeutige Inklusionsverkn&uuml;pfungen, wie Bild 7 verr&auml;t.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic007_opt.jpeg\" alt=\"pic007.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 7: OUTER JOINs mit anh&auml;ngenden Tabellen vertragen sich nicht.<\/span><\/b><\/p>\n<p>Die Meldung weist au&szlig;erdem darauf hin, dass man einige der Verkn&uuml;pfungen auf einzelne Abfragen verteilt und diese dann zusammenf&uuml;hrt. Das funktioniert schlie&szlig;lich: Sie erstellen dazu zwei Abfragen mit dem folgenden SQL-Ausdruck, die jeweils das ben&ouml;tigte Feld <b>NameAutor <\/b>(<b>tblAutoren<\/b>) beziehungsweise <b>Kategorie <\/b>(<b>tblKategorien<\/b>) und das Feld <b>DokumentID <\/b>der jeweiligen Verkn&uuml;pfungstabelle <b>tblDokumenteAutoren <\/b>und <b>tblDokumenteKategorien <\/b>enthalten und unter den Namen <b>qryDokumentAutoren <\/b>und <b>qryDokumenteKategorien <\/b>gespeichert wurden:<\/p>\n<pre>SELECT tblAutoren.NameAutor, tblDokumenteAutoren.DokumentID FROM tblAutoren INNER JOIN tblDokumenteAutoren ON tblAutoren.ID = tblDokumenteAutoren.AutorID;\r\nSELECT tblKategorien.Kategorie, tblDokumenteKategorien.DokumentID FROM tblKategorien INNER JOIN tblDokumenteKategorien ON tblKategorien.ID = tblDokumenteKategorien.KategorieID;<\/pre>\n<p>Diese beiden ergeben dann in einer weiteren Abfrage zusammen mit der Tabelle <b>tblDokumente <\/b>ein Konstrukt, das die Ausgabe von <b>OUTER JOIN<\/b>s mit anh&auml;ngenden Tabellen erlaubt (siehe Bild 8).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic008_opt.jpeg\" alt=\"pic008.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 8: Wenn man Beziehungen mit weiteren Tabellen in Abfragen versteckt, funktionieren OUTER JOINs.<\/span><\/b><\/p>\n<p><b>Minimale Abfragen<\/b><\/p>\n<p>Es w&auml;re also insgesamt m&ouml;glich, eine gro&szlig;e Abfrage zu erstellen, die alle ben&ouml;tigten Elemente enth&auml;lt und f&uuml;r die man in Abh&auml;ngigkeit von den gew&uuml;nschten Kriterien eine passende <b>WHERE<\/b>-Klausel zusammensetzt.<\/p>\n<p>Wenn man davon ausgeht, dass die Abfrage im einfachsten Fall nur die IDs der gefundenen Dokumente zur&uuml;ckliefern soll, h&auml;ngt an dieser Abfrage jedoch ein ziemlicher Overhead. Immerhin schleppt die Abfrage alle damit verkn&uuml;pften Tabellen mit, auch wenn der Benutzer m&ouml;glicherweise nur Dokumente mit einem bestimmten Namen aufgelistet bekommen m&ouml;chte. Der notwendige SQL-Ausdruck der Abfrage sieht so wie in Bild 9 aus, und dieser spart schon die wegen der mehrdeutigen Inklusionsverkn&uuml;pfung in weiteren Abfragen enthaltenen Tabellen ein. Wenn jemand nur nach einem bestimmten Dokumenttitel sucht, w&uuml;rde theoretisch ja auch die folgende Abfrage ausreichen:<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic009_opt.jpeg\" alt=\"pic009.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 9: Dieser SQL-Ausdruck liefert alle m&ouml;glichen Suchfelder der Tabellen des Beispieldatenmodells.<\/span><\/b><\/p>\n<pre>SELECT ID FROM tblDokumente\r\nWHERE Dateiname Like &apos;Access*&apos;;<\/pre>\n<p><!--30percent--><\/p>\n<p>Wenn die gefundenen Datens&auml;tze beispielsweise in einem Listenfeld angezeigt werden sollen, welches die wichtigsten Informationen der Tabelle <b>tblDokumente <\/b>anzeigt, m&uuml;ssten Sie die Tabelle <b>tblDokumente <\/b>lediglich noch mit der obigen Abfrage zusammenf&uuml;hren, statt das Gebilde aus Bild 9 zu verwenden.<\/p>\n<p><b>Dynamik ist Trumpf<\/b><\/p>\n<p>Aber ist es m&ouml;glich, immer nur die Tabellen in eine Abfrage zu integrieren, f&uuml;r die der Benutzer in einer Suche auch Kriterien angegeben hat Die Antwort lautet: Ja. Allerdings sind daf&uuml;r einige Zeilen VBA-Programmierung n&ouml;tig. Es gibt zwei M&ouml;glichkeiten:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Sie verwenden eine VBA-Routine, die eine den Kriterien des Benutzers entsprechende Abfrage zusammensetzt. Diese Aufgabe ist mit wachsender Anzahl von Tabellen nur noch schwer zu handhaben.<\/li>\n<li class=\"aufz-hlung\">Sie setzen das Abfrageergebnis in kleinen Schritten zusammen.<\/li>\n<\/ul>\n<p>Letzteres schauen wir uns in den folgenden Abschnitten im Detail an.<\/p>\n<p><b>Schritt-f&uuml;r-Schritt-Abfragen<\/b><\/p>\n<p>Bei der Schritt-f&uuml;r-Schritt-Abfrage beginnen Sie zun&auml;chst mit der Basistabelle, hier <b>tblDokumente<\/b>, und werten die Kriterien aus, die sich auf Felder dieser Tabelle beziehen. Daraus resultiert eine Abfrage und ein entsprechendes Ergebnis, das Sie in einer tempor&auml;ren Tabelle namens <b>tblTempSuche <\/b>mit den beiden Feldern <b>ID <\/b>(Autowert) und <b>DokumentID <\/b>(Zahl) zwischenspeichern. Als N&auml;chstes untersuchen Sie die Kriterien, die sich auf Lookup-Tabellen beziehen wie die <b>Dokumentart <\/b>(<b>tblDokumentarten<\/b>) oder <b>Status <\/b>(<b>tblStatus<\/b>). F&uuml;r jede Tabelle erzeugen Sie per VBA-Code wiederum ein SQL-Statement, das die Datens&auml;tze des gespeicherten Zwischenergebnisses mit dem neuen Kriterium abgleicht.<\/p>\n<p>Anschlie&szlig;end geht es an die Tabellen, die per m:n-Beziehung mit der Tabelle <b>tblDokumente <\/b>verkn&uuml;pft sind. Diese werden nach dem gleichen Schema abgearbeitet: Das aktuelle Suchzwischenergebnis wird mit dem gegebenenfalls vorhandenen Kriterium in diesen Tabellen abgeglichen und wiederum gespeichert.<\/p>\n<p><b>Suchformular<\/b><\/p>\n<p>Bevor wir uns den Details dieser Vorgehensweise zuwenden, bauen wir ein kleines Suchformular, das in den n&auml;chsten Abschnitten noch wachsen wird. Zu Beginn enth&auml;lt es lediglich ein Textfeld zur Eingabe eines Dateinamens, eine Schaltfl&auml;che zum Durchf&uuml;hren der Suche und ein Unterformular, das die gefundenen Suchergebnisse anzeigt.<\/p>\n<p>Das Unterformular <b>sfmSuche <\/b>soll einige Felder der Tabelle <b>tblDokumente <\/b>in der Datenblattansicht anzeigen (siehe Bild 10). Allerdings nur die, die auch mit den in der Tabelle <b>tblTempSuche <\/b>gespeicherten Daten &uuml;bereinstimmen, und diese liefert die Abfrage <b>qrySuchergebnis<\/b> (siehe Bild 11). <\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic010_opt.jpeg\" alt=\"pic010.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 10: Das Unterformular zeigt die Suchergebnisse in der Datenblattansicht an.<\/span><\/b><\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic012_opt.jpeg\" alt=\"pic012.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 12: Das Hauptformular der Suchfunktion in der Minimalausf&uuml;hrung<\/span><\/b><\/p>\n<p>Zu Beginn soll das Unterformular jedoch einfach an die Tabelle <b>tblDokumente <\/b>gebunden sein. Das Hauptformular sieht zun&auml;chst wie in Bild 12 aus und besitzt keine eigene Datenherkunft. Die Eigenschaften <b>Bildlaufleisten<\/b>, <b>Datensatzmarkierer<\/b>, <b>Navigationsschaltfl&auml;chen <\/b>und <b>Trennlinien <\/b>erhalten jeweils den Wert <b>Nein<\/b>.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic011_opt.jpeg\" alt=\"pic011.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 11: <\/span><\/b><\/p>\n<p>Fehlt noch die Routine, die daf&uuml;r sorgt, dass der vom Benutzer eingegebene Suchbegriff auch f&uuml;r die Suche genutzt und das Ergebnis im Unterformular angezeigt wird. Diese finden Sie in Listing 1. Die Routine l&ouml;scht zun&auml;chst alle Eintr&auml;ge der tempor&auml;ren Tabelle mit den Suchergebnissen. Dann schreibt sie die Basisabfrage in die Variable <b>strSQL<\/b>. Die <b>WHERE<\/b>-Klausel wird in der Variablen <b>strSQLWhere <\/b>zusammengesetzt.<\/p>\n<p class=\"kastentabelleheader\">Listing 1: Basisroutine zum Durchsuchen der Dokumente-Tabelle<\/p>\n<pre>Private Sub cmdSuchen_Click()\r\n    Dim strSQL As String\r\n    Dim strSQLWhere As String\r\n    Dim db As DAO.Database\r\n    Set db = CurrentDb\r\n    db.Execute &quot;DELETE FROM tblTempSuche&quot;\r\n    strSQL = &quot;SELECT ID FROM tblDokumente &quot;\r\n    If Not IsNull(Me!txtDateiname) Then\r\n        strSQLWhere = &quot;AND Dateiname LIKE &apos;*&quot; &amp; Me!txtDateiname &amp; &quot;*&apos;&quot;\r\n    End If\r\n    If Left(strSQLWhere, 4) = &quot;AND &quot; Then\r\n        strSQLWhere = Mid(strSQLWhere, 5)\r\n    End If\r\n    If Len(strSQLWhere) &gt; 0 Then\r\n        strSQLWhere = &quot;WHERE &quot; &amp; strSQLWhere\r\n        strSQL = strSQL &amp; strSQLWhere\r\n        db.Execute &quot;INSERT INTO tblTempSuche(DokumentID) &quot; &amp; strSQL\r\n        Me!sfmSuche.Form.RecordSource = &quot;qrySuchergebnis&quot;\r\n    Else\r\n        Me!sfmSuche.Form.RecordSource = &quot;tblDokumente&quot;\r\n    End If\r\nEnd Sub<\/pre>\n<p>Diese ist in der aktuellen Fassung ganz einfach und vergleicht lediglich den Dateinamen mit dem im Textfeld <b>txtDateiname <\/b>angegebenen Ausdruck. Warum aber reicht da kein Einzeiler aus, der einfach nur ein SQL-Statement wie das folgende enth&auml;lt (in einer Zeile)<\/p>\n<pre>strSQL = &quot;SELECT ID FROM tblDokumente WHERE Dateiname LIKE &apos;*&quot; &amp; Me!txtDateiname &amp; &quot;*&apos;&quot;<\/pre>\n<p>Im Falle eines einzigen Parameters h&auml;tte dies v&ouml;llig gereicht. Stattdessen pr&uuml;ft die Routine zun&auml;chst, ob das Feld <b>txtDateiname <\/b>&uuml;berhaupt einen Vergleichsausdruck enth&auml;lt, schreibt dann das Kriterium mit f&uuml;hrendem <b>AND <\/b>in die Variable <b>strSQLWhere<\/b>. Die folgende <b>If&#8230;Then<\/b>-Anweisung dient schon als Vorbereitung darauf, dass mehr als nur ein Kriterium zum Einsatz kommt:<\/p>\n<p>Sie schneidet schlicht das <b>AND<\/b> des ersten Kriteriums ab, sodass bei Verwendung zweier Kriterien ein Ausdruck wie der folgende herauskommt:<\/p>\n<pre>Kriterium1 LIKE &apos;*Wert1*&apos; AND Kriterium2 LIKE &apos;*Wert2*&apos;<\/pre>\n<p>Diesen pr&uuml;ft dann die dritte <b>If&#8230;Then<\/b>-Bedingung auf seine L&auml;nge. Ist diese gr&ouml;&szlig;er 0, liegt also ein passender Ausdruck vor, stellen die folgenden Anweisungen ein <b>WHERE <\/b>voran und h&auml;ngen das komplette Kriterium an die Basisabfrage an.<\/p>\n<p>Diese wird dann an eine <b>INSERT INTO<\/b>-Abfrage angeh&auml;ngt, welche die IDs der gefundenen Dokumente in die tempor&auml;re Tabelle <b>tblTempSuche <\/b>schreibt und die Datenherkunft des Unterformulars mit dem Suchergebnis auf die Abfrage <b>qrySuchergebnis <\/b>einstellt.<\/p>\n<p>Wenn Sie das Kriterium wie in dieser Routine zusammensetzen, k&ouml;nnen Sie weitere Vergleichsausdr&uuml;cke ohne Probleme hinzuf&uuml;gen. Im folgenden Beispiel soll der Pfad der enthaltenen Dokumente als zweiter Vergleichswert hinzukommen.<\/p>\n<p>Dazu brauchen Sie im Hauptformular nur ein zweites Textfeld namens <b>txtPfad <\/b>anzulegen und in die Routine, die durch den Klick auf die Schaltfl&auml;che <b>cmdSuchen <\/b>ausgel&ouml;st wird, die folgenden Zeilen einzubauen &#8211; und zwar hinter der ersten <b>If&#8230;Then<\/b>-Bedingung:<\/p>\n<pre>If Not IsNull(Me!txtPfad) Then\r\n    strSQLWhere = &quot;AND Pfad LIKE &apos;*&quot; _\r\n    &amp; Me!txtPfad &amp; &quot;*&apos;&quot;\r\nEnd If<\/pre>\n<p>Auf die gleiche Weise verfahren Sie mit weiteren Feldern, die direkt in der Tabelle <b>tblDokumente <\/b>enthalten sind.<\/p>\n<p class=\"zwischen-berschrift-oberer-spaltenrand\">Suche in Lookup-Tabellen<\/p>\n<p>In Lookup-Tabellen wie etwa <b>tblDokumentarten <\/b>oder <b>tblStatus<\/b> kann man auf mindestens zwei Arten suchen, wenn man anschlie&szlig;end die IDs der Dokumente mit den gesuchten Eigenschaften erhalten m&ouml;chte.<\/p>\n<p>Die erste l&auml;sst dem Suchenden v&ouml;llig freie Hand und erlaubt die Eingabe beliebiger Texte, nach denen dann zun&auml;chst die Datens&auml;tze der Lookup-Tabelle durchsucht und anschlie&szlig;end die korrespondierenden Dokumente ermittelt werden. Die Eingabe des Suchbegriffs erfolgt hier mit einem Textfeld.<\/p>\n<p>Die zweite Methode ist komfortabler, aber auch weniger flexibel. Sie basiert auf der Anzeige aller in der Lookup-Tabelle enthaltenen Eintr&auml;ge in einem Kombinationsfeld. <\/p>\n<p>Auf diese Weise braucht der Anwender nur noch den passenden Eintrag auszuw&auml;hlen, wobei er unterst&uuml;tzend die ersten paar Zeichen eingibt und somit schneller zum gesuchten Eintrag springt.<\/p>\n<p class=\"zwischen-berschrift-oberer-spaltenrand\">Vorgehensweise bei Daten aus verkn&uuml;pften Tabellen<\/p>\n<p>Die Routine aus Listing 1 m&uuml;ssen Sie aufbrechen, um die aus anderen Tabellen stammenden Informationen zu durchsuchen. Wie bereits oben angek&uuml;ndigt, verwenden wir hier keine einzelne gro&szlig;e Abfrage, um die gesuchten Datens&auml;tze zu finden, sondern mehrere aufeinanderfolgende, einfache Abfragen, die ihr Ergebnis jeweils in einer tempor&auml;ren Tabelle zwischenspeichern.<\/p>\n<p>Nachdem diese nach der ersten Abfrage mit Informationen gef&uuml;llt ist, soll die zweite Abfrage nur noch die in der tempor&auml;ren Tabelle gespeicherten Datens&auml;tze durchsuchen und diejenigen, die auch den Kriterien der zweiten Abfrage entsprechen, wiederum dort eintragen. Eigentlich greifen Sie w&auml;hrend dieses Vorgangs also lesend und schreibend auf die Tabelle <b>tblTempSuche <\/b>zu, was gewisse Probleme mit sich bringt: Irgendwie m&uuml;ssen Sie ja nach dem Speichern des aktuellen Suchergebnisses das vorherige Ergebnis l&ouml;schen. Daher speichert man die ID des zuletzt hinzugef&uuml;gten Datensatzes jeweils zwischen, um nach dem Schreiben der Datens&auml;tze des neuen Suchergebnisses die alten Ergebnisse zu l&ouml;schen.<\/p>\n<p>Ein weiteres Problem besteht darin, dass das Unterformular beim &Ouml;ffnen oder nach dem L&ouml;schen der Suchkriterien zun&auml;chst alle Datens&auml;tze anzeigen soll, die in diesem Fall direkt aus der Tabelle <b>tblDokumente <\/b>stammen. Liegt mindestens ein Kriterium vor, kommt das Ergebnis jedoch aus einer Abfrage, die alle Datens&auml;tze der Tabelle <b>tblDokumente <\/b>liefert, deren ID in der tempor&auml;ren Tabelle <b>tblSucheTemp <\/b>aufgef&uuml;hrt sind. Damit die Routine nach dem Ermitteln der den Suchkriterien entsprechenden Datens&auml;tze die richtige Datenherkunft anzeigt, gibt es eine Boolean-Variable namens <b>bolRecordsFound<\/b>, die auf <b>True <\/b>eingestellt wird, sobald die Routine erstmals einen Datensatz in die Tabelle <b>tblSucheTemp <\/b>geschrieben hat. Gleiches gilt f&uuml;r die Basisabfrage. Diese hei&szlig;t zu Beginn der Routine so:<\/p>\n<pre>SELECT ID FROM tblDokumente<\/pre>\n<p>Sobald aber ein Kriterium ausgewertet wurde und die passenden Datens&auml;tze in die Tabelle <b>tblSucheTemp <\/b>gelangt sind, d&uuml;rfen Sie die folgenden Kriterien nicht mehr auf diese Basisabfrage anwenden, denn somit w&uuml;rden ja die zuvor ermittelten und in der Tabelle <b>tblSucheTemp <\/b>gespeicherten Datens&auml;tze nicht ber&uuml;cksichtigt.<\/p>\n<p>Deshalb schreiben Sie, sobald eines der Kriterien zu einer Ergebnismenge gef&uuml;hrt hat, eine neue Basisabfrage in die Stringvariable <b>strSQL<\/b>:<\/p>\n<pre>strSQL = &quot;SELECT ID FROM tblTempSuche&quot;<\/pre>\n<p><b>Lookup-Felder per Texteingabe durchsuchen<\/b><\/p>\n<p>Mit diesen Hinweisen k&ouml;nnen Sie die Routine aus Listing 1 in die aus Listing 2 &uuml;berf&uuml;hren. Sie enth&auml;lt die angesprochenen Punkte sowie eine weitere Suche, die sich um die im Feld <b>Dokumentarten <\/b>der Lookup-Tabelle <b>tblDokumentarten <\/b>enthaltenen Texte k&uuml;mmert. Die Eingabe des Suchkriteriums erfolgt &uuml;ber das Textfeld <b>txtDokumentart<\/b>, die Suche nach den richtigen Datens&auml;tzen prinzipiell &uuml;ber eine Abfrage wie die folgende:<\/p>\n<p class=\"kastentabelleheader\">Listing 2: Diese Routine durchsucht sowohl in der Haupttabelle enthaltene Felder als auch solche, die sich in einer Lookup-Tabelle befinden.<\/p>\n<pre>Private Sub cmdSuchen_Click()\r\n    Dim strSQL As String\r\n    Dim strSQLWhere As String\r\n    Dim db As DAO.Database\r\n    Dim bolResultsFound As Boolean\r\n    Dim lngLastID As Long\r\n    Dim lngLastIDTemp As Long\r\n    Set db = CurrentDb\r\n    db.Execute &quot;DELETE FROM tblTempSuche&quot;\r\n    strSQL = &quot;SELECT ID FROM tblDokumente &quot;\r\n    &apos;Dateinamen\r\n    If Not IsNull(Me!txtDateiname) Then\r\n        strSQLWhere = &quot;AND Dateiname LIKE &apos;*&quot; &amp; Me!txtDateiname &amp; &quot;*&apos;&quot;\r\n    End If\r\n    &apos;Verzeichnisse\r\n    If Not IsNull(Me!txtPfad) Then\r\n        strSQLWhere = &quot;AND Pfad LIKE &apos;*&quot; &amp; Me!txtPfad &amp; &quot;*&apos;&quot;\r\n    End If\r\n    &apos;Einfache Kriterien, die sich in der Haupttabelle befinden, auswerten und\r\n    &apos;das Ergebnis in die Tabelle tblSucheTemp schreiben.\r\n    If Left(strSQLWhere, 4) = &quot;AND &quot; Then\r\n        strSQLWhere = Mid(strSQLWhere, 5)\r\n    End If\r\n    If Len(strSQLWhere) &gt; 0 Then\r\n        strSQLWhere = &quot;WHERE &quot; &amp; strSQLWhere\r\n        strSQL = strSQL &amp; strSQLWhere\r\n        db.Execute &quot;INSERT INTO tblTempSuche(ID) &quot; &amp; strSQL\r\n        lngLastID = db.OpenRecordset(&quot;SELECT @@IDENTITY&quot;).Fields(0)\r\n        strSQL = &quot;SELECT ID FROM tblTempSuche&quot;\r\n        bolRecordsfound = True\r\n    End If\r\n    &apos;Dokumentarten\r\n    If Not IsNull(Me!txtDokumentart) Then\r\n        strSQLWhere = &quot;WHERE ID IN (SELECT ID FROM qrySucheDokumentarten WHERE Dokumentart &quot; _\r\n        &amp; &quot;LIKE &apos;*&quot; &amp; Me!txtDokumentart &amp; &quot;*&apos;)&quot;\r\n        strSQL = strSQL &amp; &quot; &quot; &amp; strSQLWhere\r\n        db.Execute &quot;INSERT INTO tblTempSuche(ID) &quot; &amp; strSQL\r\n        lngLastIDTemp = db.OpenRecordset(&quot;SELECT @@IDENTITY&quot;).Fields(0)\r\n        db.Execute &quot;DELETE FROM tblTempSuche WHERE TempSucheID &lt;= &quot; &amp; lngLastID, _\r\n        dbFailOnError\r\n        lngLastID = lngLastIDTemp\r\n        strSQL = &quot;SELECT ID FROM tblTempSuche&quot;\r\n        bolRecordsfound = True\r\n    End If\r\n    If bolRecordsfound Then\r\n        Me!sfmSuche.Form.RecordSource = &quot;qrySuchergebnis&quot;\r\n    Else\r\n        Me!sfmSuche.Form.RecordSource = &quot;tblDokumente&quot;\r\n    End If\r\nEnd Sub\r\nSELECT tblDokumente.ID,\r\ntblDokumentarten.Dokumentart\r\nFROM tblDokumentarten\r\nINNER JOIN tblDokumente\r\nON tblDokumentarten.ID =\r\ntblDokumente.DokumentartID\r\nWHERE tblDokumentarten.Dokumentart\r\nLIKE &apos;*Suchbegriff*&apos;;<\/pre>\n<p>Der kleine Unterschied ist, dass sich diese Abfrage hier unter Umst&auml;nden auf die Tabelle mit den durch die vorherigen Kriterien ermittelten Datens&auml;tzen st&uuml;tzen muss, die in der Tabelle <b>tblSucheTemp<\/b> gespeichert sind. Und genau dies erledigt der fett hervorgehobene Teil aus Listing 2: Er setzt die SQL-Abfrage zusammen, welche die IDs aller passenden Dokumente liefert, schreibt diese IDs in die Tabelle <b>tblSucheTemp <\/b>und l&ouml;scht die bisher gefundenen Datens&auml;tze aus dieser Tabelle.<\/p>\n<p>Weitere Suchfelder, die sich auf Felder in Lookup-Tabellen beziehen, k&ouml;nnen Sie durch Hinzuf&uuml;gen eines passenden Textfelds sowie Kopieren und Anpassen des in Listing 2 fett gedruckten Teils erstellen.<\/p>\n<p class=\"zwischen-berschrift-oberer-spaltenrand\">Lookup-Felder per Auswahl durchsuchen<\/p>\n<p>Komfortabler ist es, wenn der Benutzer einen Suchbegriff auf allen bereits vorhandenen Eintr&auml;gen des Lookup-Felds ausw&auml;hlen kann. Dazu f&uuml;gen Sie kein Textfeld, sondern ein Kombinationsfeld hinzu, das als Datensatzherkunft eine Abfrage auf Basis der Lookup-Tabelle enth&auml;lt, welche die ID und den anzuzeigenden Text liefert. In unserem Beispiel lautet der SQL-Ausdruck f&uuml;r die Datensatzherkunft etwa wie folgt:<\/p>\n<pre>SELECT ID, Dokumentart FROM tblDokumentarten;<\/pre>\n<p>Die Eigenschaften <b>Spaltenanzahl <\/b>und <b>Spaltenbreiten <\/b>stellen Sie auf <b>2 <\/b>und <b>0cm <\/b>ein, damit das Kombinationsfeld nur das zweite Feld der Datensatzherkunft anzeigt und das erste lediglich als gebundenes Feld dient.<\/p>\n<p>Der Codeausschnitt aus Listing 3 zeigt, welche Zeilen Sie der Prozedur <b>cmdSuchen_Click <\/b>hinzuf&uuml;gen m&uuml;ssen, damit auch der Inhalt des Kombinationsfelds in die Suche mit einbezogen wird. Der Ausschnitt sieht fast genau so aus wie der aus dem Beispiel zur Suche nach einem im Feld <b>Dokumentart <\/b>enthaltenen Text, unterscheidet sich jedoch in der verwendeten <b>WHERE<\/b>-Bedingung.<\/p>\n<p class=\"kastentabelleheader\">Listing 3: Dieser Abschnitt der Routine cmdSuchen_Click filtert das Suchergebnis nach der im Kombinationsfeld cboDokumentarten angegebenen Dokumentart.<\/p>\n<pre>If Not Me!cboDokumentart = 0 Then\r\n    strSQLWhere = &quot;WHERE ID IN (SELECT ID FROM tblDokumente WHERE DokumentartID = &quot; _\r\n    &amp; Me.cboDokumentart &amp; &quot;)&quot;\r\n    strSQL = strSQL &amp; &quot; &quot; &amp; strSQLWhere\r\n    db.Execute &quot;INSERT INTO tblTempSuche(ID) &quot; &amp; strSQL\r\n    lngLastIDTemp = db.OpenRecordset(&quot;SELECT @@IDENTITY&quot;).Fields(0)\r\n    db.Execute &quot;DELETE FROM tblTempSuche WHERE TempSucheID &lt;= &quot; &amp; lngLastID, dbFailOnError\r\n    lngLastID = lngLastIDTemp\r\n    strSQL = &quot;SELECT ID FROM tblTempSuche&quot;\r\n    bolRecordsfound = True\r\nEnd If<\/pre>\n<p><b>m:n-Beziehungen nach einzelnen Eintr&auml;gen durchsuchen<\/b><\/p>\n<p>Ob eine Tabelle per 1:n-Beziehung wie im obigen Fall der Lookup-Tabelle oder per m:n-Beziehung mit der Haupttabelle verkn&uuml;pft ist, deren Datens&auml;tze als Suchergebnis zur&uuml;ckgeliefert werden sollen, spielt nur eine untergeordnete Rolle.<\/p>\n<p>Als Beispiel dient hier die Tabelle <b>tblAutoren<\/b>, die &uuml;ber die Tabelle <b>tblDokumenteAutoren <\/b>mit der Tabelle <b>tblDokumente <\/b>verkn&uuml;pft ist.<\/p>\n<p>&Uuml;ber ein Kombinationsfeld, das alle in der Tabelle <b>tblAutoren <\/b>gespeicherten Autoren zur Auswahl anbietet, soll der Benutzer den Autor festlegen, dessen Dokumente er aufgelistet bekommen m&ouml;chte.<\/p>\n<p>Das Kombinationsfeld enth&auml;lt als Datenherkunft die Tabelle <b>tblAutoren <\/b>mit den Feldern <b>ID <\/b>und <b>NameAutor<\/b>. Der Code, der das mit diesem Kombinationsfeld festgelegte Kriterium auswertet, unterscheidet sich lediglich in einer Zeile von dem aus Listing 3. Diese Zeile legt die <b>WHERE<\/b>-Bedingung fest:<\/p>\n<pre>strSQLWhere = &quot;WHERE ID IN (SELECT DokumentID FROM tblDokumenteAutoren WHERE AutorID = &quot; &amp; Me!cboAutoren &amp; &quot;)&quot;<\/pre>\n<p><b>m:n-Beziehungen per AND und OR nach <\/b><\/p>\n<pre>mehreren Kriterien gleichzeitig durchsuchen<\/pre>\n<p>Viel spannender ist es, die Dokumente zu suchen, die mindestens einen oder alle von mehreren angegebenen Autoren aufweisen, also beispielsweise alle Dokumente, die von einem der beiden Autoren <b>Andr&eacute; Minhorst <\/b>oder <b>Sascha Trowitzsch <\/b>geschrieben wurden, oder alle Dokumente, die beide gleichzeitig als Autoren aufweisen.<\/p>\n<p>Erstmal brauchen Sie daf&uuml;r eine geeignete Eingabem&ouml;glichkeit. Da gibt es verschiedene Varianten: Sie k&ouml;nnten gleich mehrere Kombinationsfelder anlegen, mit denen Sie die per <b>OR<\/b> oder <b>AND <\/b>verkn&uuml;pften Suchbegriffe auf Basis der gleichen m:n-Beziehung festlegen. Nachteil ist, dass Sie eine feste Anzahl an M&ouml;glichkeiten festlegen m&uuml;ssen und dass diese auch immer den gleichen Platz einnehmen &#8211; auch, wenn der Benutzer gerade nur einen einzigen Eintrag der verkn&uuml;pften Tabelle als Vergleichskriterium verwenden m&ouml;chte. Der Vorteil ist die relativ einfache Programmierung.<\/p>\n<p>Die zweite Variante ist ein Kombinationsfeld, gepaart mit einer Schaltfl&auml;che, mit der Sie den aktuell im Kombinationsfeld ausgew&auml;hlten Eintrag in ein Textfeld eintragen (siehe Bild 13). Der Vorteil ist der mit einer einzigen Zeile geringe Platzbedarf, der Nachteil eine relativ aufwendige Programmierung: Die in dem Textfeld gespeicherten Ausdr&uuml;cke helfen nicht viel weiter, wenn es um das Suchen selbst geht, denn diese Suche muss &uuml;ber die ID des jeweiligen Eintrags der verkn&uuml;pften Tabelle, hier <b>tblAutoren<\/b>, geschehen.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic013_opt.jpeg\" alt=\"pic013.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 13: Ausw&auml;hlen von Kriterien via Kombinationsfeld<\/span><\/b><\/p>\n<p>Daher speichert man sie in dieser Variante zwischen &#8211; und zwar in der Eigenschaft <b>Tag <\/b>eines Steuerelements, hier dem Textfeld. Beim Durchf&uuml;hren der Suche muss man diese Eigenschaft dann noch parsen, um die durch ein Trennzeichen nach Wahl separierten Werte auszulesen und die entsprechende SQL-Abfrage zusammenzustellen.<\/p>\n<p>Die dritte Variante wieder weniger platzsparend, daf&uuml;r aber recht flexibel: Sie verwenden hier zwei Listenfelder, von denen das erste alle Eintr&auml;ge anzeigt, nach denen gefahndet werden soll, und das zweite alle &uuml;brigen. Die Suchbegriffe sollen dabei per Doppelklick oder durch entsprechende Schaltfl&auml;chen (siehe Bild 14) von einem ins andere Listenfeld geschoben werden. Die Auswertung der Suchbegriffe ist hier wesentlich einfacher als im vorigen Beispiel.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2008_04\/Suche-web-images\/pic014_opt.jpeg\" alt=\"pic014.tif\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 14: Kriterien f&uuml;r Suche in m:n-Beziehungen per Listenfeld ausw&auml;hlen<\/span><\/b><\/p>\n<p>Da die Beschreibung dieser Varianten den Rahmen dieses Beitrags sprengen w&uuml;rde, finden Sie diese in einem weiteren Artikel in der folgenden Ausgabe von Access im Unternehmen (<b>Suchen in m:n-Beziehungen<\/b>, Shortlink 630).<\/p>\n<p><b>Suchen in entfernten Tabellen<\/b><\/p>\n<p>Gegebenenfalls m&uuml;ssen Sie einmal nach Daten in Feldern von Tabellen suchen, die weiter als nur eine 1:n- oder m:n-Verkn&uuml;pfung von der Tabelle, deren Datens&auml;tze als Suchergebnis geliefert werden sollen, entfernt ist.<\/p>\n<p>In diesem Fall gehen Sie &auml;hnlich wie bei 1:n- oder m:n-Beziehungen vor, ersetzen aber die <b>WHERE<\/b>-Bedingung so, dass alle Tabellen von der Basistabelle bis zur Tabelle mit dem Kriteriumsfeld enthalten sind.<\/p>\n<p><b>Zusammenfassung und Ausblick<\/b><\/p>\n<p>Mit den hier vorgestellten Vorgehensweisen k&ouml;nnen Sie Datens&auml;tze aus einer Tabelle mit Suchkriterien aus der gleichen oder aus verkn&uuml;pften Tabellen ermitteln. Mit den Erweiterungen aus dem oben erw&auml;hnten Beitrag gelingt dies auch f&uuml;r mehrere per <b>OR<\/b> oder <b>AND <\/b>verkn&uuml;pfte Elemente von Suchbegriffen aus m:n-Beziehungen.<\/p>\n<p><b><span style=\"color:darkgrey\">Datenherkunft des Unterformulars sfmSuche.<\/span><\/b><\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>Suche.mdb<\/p>\n<p>Suche.mdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/6701F62E-171D-4A5D-8BD0-62662A65978D\/aiu_619.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Eine einfache Suchfunktion ist schnell gebaut. Ein Suchfeld einrichten, eine Schaltfl&auml;che mit dem notwendigen VBA-Code anlegen und schlie&szlig;lich ein Steuerelement zum Anzeigen des Suchergebnisses. Was aber, wenn es nicht nur eines, sondern viele Kriterien gibt, und diese sich auch noch &uuml;ber mehrere Tabellen erstrecken Dieser Beitrag diskutiert die M&ouml;glichkeiten und zeigt einen Ansatz, mit dem Sie auf jeden Fall den &Uuml;berblick behalten &#8211; egal, wie viele Kriterien und Tabellen die Suche umfasst.<\/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":[662008,66042008,44000036,44000023,44000025],"tags":[],"class_list":["post-55000619","post","type-post","status-publish","format-standard","hentry","category-662008","category-66042008","category-Daten_suchen_sortieren_gruppieren","category-Mit_Formularen_arbeiten","category-VBA_und_Programmiertechniken"],"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>Suchfunktionen von einfach bis komplex - 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\/Suchfunktionen_von_einfach_bis_komplex\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Suchfunktionen von einfach bis komplex\" \/>\n<meta property=\"og:description\" content=\"Eine einfache Suchfunktion ist schnell gebaut. Ein Suchfeld einrichten, eine Schaltfl&auml;che mit dem notwendigen VBA-Code anlegen und schlie&szlig;lich ein Steuerelement zum Anzeigen des Suchergebnisses. Was aber, wenn es nicht nur eines, sondern viele Kriterien gibt, und diese sich auch noch &uuml;ber mehrere Tabellen erstrecken Dieser Beitrag diskutiert die M&ouml;glichkeiten und zeigt einen Ansatz, mit dem Sie auf jeden Fall den &Uuml;berblick behalten - egal, wie viele Kriterien und Tabellen die Suche umfasst.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2021-02-11T21:21:49+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg03.met.vgwort.de\/na\/0657af7ab58247838072c8162700a132\" \/>\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=\"23\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Suchfunktionen_von_einfach_bis_komplex\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Suchfunktionen_von_einfach_bis_komplex\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Suchfunktionen von einfach bis komplex\",\"datePublished\":\"2021-02-11T21:21:49+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Suchfunktionen_von_einfach_bis_komplex\\\/\"},\"wordCount\":4032,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Suchfunktionen_von_einfach_bis_komplex\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg03.met.vgwort.de\\\/na\\\/0657af7ab58247838072c8162700a132\",\"articleSection\":[\"2008\",\"4\\\/2008\",\"Daten suchen, sortieren, gruppieren\",\"Mit Formularen arbeiten\",\"VBA und Programmiertechniken\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Suchfunktionen_von_einfach_bis_komplex\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Suchfunktionen_von_einfach_bis_komplex\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Suchfunktionen_von_einfach_bis_komplex\\\/\",\"name\":\"Suchfunktionen von einfach bis komplex - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Suchfunktionen_von_einfach_bis_komplex\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Suchfunktionen_von_einfach_bis_komplex\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg03.met.vgwort.de\\\/na\\\/0657af7ab58247838072c8162700a132\",\"datePublished\":\"2021-02-11T21:21:49+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Suchfunktionen_von_einfach_bis_komplex\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Suchfunktionen_von_einfach_bis_komplex\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Suchfunktionen_von_einfach_bis_komplex\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg03.met.vgwort.de\\\/na\\\/0657af7ab58247838072c8162700a132\",\"contentUrl\":\"http:\\\/\\\/vg03.met.vgwort.de\\\/na\\\/0657af7ab58247838072c8162700a132\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Suchfunktionen_von_einfach_bis_komplex\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Suchfunktionen von einfach bis komplex\"}]},{\"@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":"Suchfunktionen von einfach bis komplex - 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\/Suchfunktionen_von_einfach_bis_komplex\/","og_locale":"de_DE","og_type":"article","og_title":"Suchfunktionen von einfach bis komplex","og_description":"Eine einfache Suchfunktion ist schnell gebaut. Ein Suchfeld einrichten, eine Schaltfl&auml;che mit dem notwendigen VBA-Code anlegen und schlie&szlig;lich ein Steuerelement zum Anzeigen des Suchergebnisses. Was aber, wenn es nicht nur eines, sondern viele Kriterien gibt, und diese sich auch noch &uuml;ber mehrere Tabellen erstrecken Dieser Beitrag diskutiert die M&ouml;glichkeiten und zeigt einen Ansatz, mit dem Sie auf jeden Fall den &Uuml;berblick behalten - egal, wie viele Kriterien und Tabellen die Suche umfasst.","og_url":"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/","og_site_name":"Access im Unternehmen","article_published_time":"2021-02-11T21:21:49+00:00","og_image":[{"url":"http:\/\/vg03.met.vgwort.de\/na\/0657af7ab58247838072c8162700a132","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"23\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Suchfunktionen von einfach bis komplex","datePublished":"2021-02-11T21:21:49+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/"},"wordCount":4032,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/#primaryimage"},"thumbnailUrl":"http:\/\/vg03.met.vgwort.de\/na\/0657af7ab58247838072c8162700a132","articleSection":["2008","4\/2008","Daten suchen, sortieren, gruppieren","Mit Formularen arbeiten","VBA und Programmiertechniken"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/","url":"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/","name":"Suchfunktionen von einfach bis komplex - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/#primaryimage"},"thumbnailUrl":"http:\/\/vg03.met.vgwort.de\/na\/0657af7ab58247838072c8162700a132","datePublished":"2021-02-11T21:21:49+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/#primaryimage","url":"http:\/\/vg03.met.vgwort.de\/na\/0657af7ab58247838072c8162700a132","contentUrl":"http:\/\/vg03.met.vgwort.de\/na\/0657af7ab58247838072c8162700a132"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Suchfunktionen_von_einfach_bis_komplex\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Suchfunktionen von einfach bis komplex"}]},{"@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\/55000619","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=55000619"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000619\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000619"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000619"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000619"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}