Eine Datenbank ohne Suche ist wie ein Auto ohne Motor: Schick anzusehen, aber zu nichts zu gebrauchen. Deswegen widmet sich der zweite Teil unseres Base-Einstiegs dem Implementieren einer Suchfunktion.
Der erste Teil unserer kleinen Serie erläuterte, wie Sie eine Bilddatenbank mit komfortabler Eingabemaske und einem Tagging-System (Abbildung 1) erstellen. Dabei löst Base [1] seinen Anspruch, Datenbankprogrammierung per Mausklick und ohne Kenntnisse in SQL zu ermöglichen, unbeschränkt ein: Assistenten und ein grafischer Abfrage-Editor erledigen die Arbeit und ermöglichen auch Anwendern ohne Programmiererfahrung das Erstellen einer Datenbank.

Abbildung 1: Aus drei Tabellen, einer Abfrage und einem Eingabeformular entstand im vorigen Teil dieses Artikels eine Bilddatenbank, der bislang noch eine Suchfunktion fehlt.
Doch der Base-Anwendung aus dem ersten Teil (bilddatenbank_teil_1.odb auf der Heft-DVD) fehlt noch ein wichtiges Feature: die Suchfunktion (Abbildung 2). Bei dieser Aufgabe müssen die grafischen Helfer in Base jedoch die Waffen strecken – hier geht es ohne Handarbeit nicht weiter.

Abbildung 2: Niemand möchte durch alle Datensätze blättern, um ein bestimmtes Bild zu finden. Die Titelsuche oben im Formular schafft Abhilfe.
Handarbeit
Eine Abfrage, die zu einem per Formular eingegebenen Suchbegriff passende Datensätze herausfiltert, lässt sich nicht mit dem grafischen Editor erzeugen. Sie setzt handgeschriebenen SQL-Code voraus, wie ihn Programmierer zur Kommunikation mit Datenbanken nutzen – erfreulicherweise jedoch nur in homöopathischer Dosierung.
Die für Programmierer triviale Aufgabe, einen vom Benutzer eingegebenen Suchbegriff in eine ansonsten feststehende Abfrage einzufügen, lässt sich in Base nur über ein Hintertürchen umsetzen. Abbildung 3 verbildlicht, wie das funktioniert: Die Tabelle Filter (blau) enthält nur einen Datensatz mit einem Suchbegriff – in unserem Beispiel der Titel.

Titel-Wert des einzigen Datensatzes der Tabelle Filter. Ein Unterformular, das auf Filter zugreift, verändert diesen Wert, und stößt damit eine Suche nach dem passenden Titel an.” width=”300″ height=”67″ />
Titel-Wert des einzigen Datensatzes der Tabelle Filter. Ein Unterformular, das auf Filter zugreift, verändert diesen Wert, und stößt damit eine Suche nach dem passenden Titel an.Den in Filter gespeicherten Titel verändert ein Unterformular – ähnlich dem im ersten Teil erläuterten Kategorien-Unterformular. Die Suchabfrage (rot) vergleicht den Filter-Titel mit den Titel-Feldern in der Tabelle Bilder (gelb) und gibt nur jene Datensätze zurück, für die beide übereinstimmen.
Abbildung 2 zeigt eine erweiterte Version des Formulars Bilder: Oben sehen Sie blau hinterlegt die Filterfunktion, die nach Bildern mit einem bestimmten Titel sucht. Bleibt das Filterfeld leer, blättern Sie wie gehabt im Hauptformular durch alle Datensätze. Nach Eingabe eines Suchbegriffs erscheinen aber nur noch Datensätze, die zum Suchbegriff passen.
Datenpuffer
Um an Bekanntes anzuknüpfen, erstellen Sie zuerst eine Tabelle mit dem Feldnamen Titel, die den wechselnden Suchbegriff aufnimmt. Gestatten Sie es Base, der Tabelle automatisch einen Primärschlüssel hinzuzufügen, sonst lässt sich deren Inhalt nicht per Formular verändern.
Als Nächstes benötigten Sie ein weiteres Formular, das auf die eben erstellte Tabelle Filter zugreift. Öffnen Sie dazu den Formular-Navigator und erstellen Sie per Rechtsklick auf Formulare das neue Formular Filter. Da dieses Formular die Datenanzeige im bisherigen Hauptformular steuert, ziehen Sie mainForm auf Filter und ordnen es ihm damit unter.
Als Nächstes kümmern Sie sich um die Bindung des Filter-Formulars an die gleichnamige Tabelle. Öffnen Sie dazu mithilfe des Buttons Formular in der linken Schalterleiste (vierter von oben) die Einstellungspalette des Formulars.
Abbildung 4 zeigt die erforderlichen Einstellungen für den Reiter Daten. Neben der Auswahl der Tabelle fällt die auf aktueller Datensatz gesetzte Einstellung Zyklus auf. Sie bewirkt, dass Sie über das Formular keine neuen Datensätze eingeben, sondern nur einen bestehenden verändern. Es darf schließlich immer nur einen aktuell gültigen Suchbegriff geben.

Aktueller Datensatz beschränkt die Dateneingabe eines Formulars auf den aktuellen Datensatz.” width=”300″ height=”174″ />
Abbildung 4: Der ZyklusAktueller Datensatz beschränkt die Dateneingabe eines Formulars auf den aktuellen Datensatz.Nicht mehr per Mausklick
Deutlich komplizierter wird es bei der Abfrage, die alle Datensätze aus Bild zurückgibt, die zum in Filter gespeicherten Suchbegriff passen: Dazu müssen Sie per Hand SQL-Code schreiben. Wählen Sie dafür im Base-Hauptfenster in der Rubrik Abfragen die Option Abfrage in der SQL Ansicht erstellen.
Das Base-Handbuch [2] nennt unter der Überschrift Allgemeines zu Datenbankaufgaben / Datenfilterung als ersten Ausgangspunkt einen passenden SQL-Code. In Listing 1 sehen Sie eine bereits an die Feld- und Tabellennamen aus unserem Beispiel angepasste Fassung.
Listing 1
SELECT * FROM "Bilder" WHERE "Titel" = IFNULL( ( SELECT "Titel" FROM "Filter" ), "Titel" )
Der Kopf SELECT * FROM wählt alle Felder der Tabelle Bilder aus. Die hinter der Klausel WHERE genannte Bedingung wählt bestimmte Datensätze aus. "Titel" = weist die Datenbank an, das Feld Titel in der SELECT genannten Tabelle (also Bilder) mit dem Wert nach dem Gleichheitszeichen zu vergleichen und Datensätze auszuschließen, bei denen der Vergleich nicht zutrifft.
Eine weitere SELECT-Klausel, die diesmal aber die Tabelle Filter referenziert, liefert den Vergleichswert. Die Abfrage filtert also alle Datensätze heraus, bei der das Feld Titel in der Tabelle Bilder dem gleichnamigen Feld in Filter entspricht. Die den zweiten SELECT kapselnde Funktion IFNULL setzt diese Einschränkung allerdings außer Kraft, wenn das Titel-Feld in Filter leer ist.
IFNULL gibt den im ersten Parameter genannten Wert zurück, sofern er ungleich null ist, sonst den zweiten Parameter "Titel". Diese Zeichenkette in Anführungszeichen wertet die Datenbank als einen Feldnamen aus dem primären SELECT. Sie vergleicht also, sofern Titel in Filter leer bleibt, das Feld Titel mit sich selbst, was immer wahr ergeben sollte. So kommt das für eine Filterfunktion passende Verhalten zustande, dass bei leerem Filterwert alle Datensätze erscheinen – zumindest in der Theorie.
Allerdings hintertreiben Eigenarten von SQL und der IFNULL-Funktion die scheinbar selbstverständliche Annahme, dass der Vergleich eines Feldes mit sich selbst immer wahr ergibt: Ist das Feld nämlich leer, so liefert SELECT den Wert NULL, die Funktion IFNULL aber eine leere Zeichenkette – für die Datenbank ist das nicht dasselbe. Es fehlen also bei leerem Filterfeld alle Datensätze, in denen Sie das Beschreibungsfeld nicht ausgefüllt haben.
Erste Hilfe
Wenn Ihnen der Workaround nicht ausreicht, im Entwurf der Tabelle für Bild leere Titel-Felder mithilfe der Einstellung Eingabe erforderlich = ja für das Feld Titel auszuschließen, bleibt nur die Lösung, den Rückgabewert des SELECT ebenfalls mit einer IFNULL-Funktion zu kapseln (Listing 2).
Listing 2
SELECT "Bilder".* , IFNULL( "Titel", '' ) AS "T" FROM "Bilder" WHERE "T" = IFNULL( ( SELECT "Titel" FROM "Filter" ), "T" )
Anders als im Handbuch verwendet das Beispiel außerdem vor dem Asterisk (*), der alle Felder der Tabelle Bilder auswählt, noch den Tabellennamen "Bilder", obwohl er schon eindeutig aus der FROM-Klausel hervorgeht. Doch ohne diese Ergänzung meldet Base 4.2.3 einen Syntaxfehler. Vermutlich handelt es sich dabei um einen Bug im SQL-Parser, denn die doppelte Angabe des Tabellennamens ergibt keinen Sinn. Sie wäre in anderen Datenbanken nicht nötig, auch nicht in früheren Base-Versionen.
Dann vergleicht die WHERE-Klausel die Rückgabe der IFNULL-Funktion mit der mittels des Schlüsselworts AS dem Alias T zugewiesenen Rückgabe der neu hinzugekommenen IFNULL-Funktion. Diese liefert ebenfalls niemals NULL, sondern bei leeren Feldern '', also einen leeren String. Jetzt funktioniert die Filterabfrage wie gewünscht.
Nun darf MainForm seine Daten nicht mehr direkt aus der Tabelle Bilder beziehen, sondern über die zwischengeschaltete Filter-Abfrage. Ändern Sie daher die Datenbindung von MainForm zu Abfrage: FilterAbfrage
Damit sich die Filterfunktion aus dem Formular heraus bedienen lässt, fehlt noch eine Kleinigkeit: Fügen Sie dem MainForm eine Schaltfläche (Button auf der linken Symbolleiste im Formularentwurf) hinzu und wählen Sie in dessen Eigenschaften unten im Reiter Allgemein als Aktion Formular aktualisieren. Erst nach einem Klick auf diesen Button zeigt MainForm den zum Begriff im Filter-Feld passenden Datensatz an.
Abbildung 2 zeigt im Vergleich zu früheren Versionen des Eingabeformulars außerdem noch das Feld Dateipfad: So erscheint nicht nur eine Vorschau des Bilds, sondern auch dessen Ort im Dateisystem. Dabei handelt es sich um ein Textfeld mit dem Inhalt Dateipfad.
Die Suchfunktion lässt sich auch auf weitere Datenfelder ausweiten: Jedes weitere Feld setzt einen weiteren IFNULL-Aufruf in der SELECT-Klausel am Anfang der Abfrage voraus sowie ein IFNULL in der WHERE-Klausel, das die Unterabfrage kapselt. Listing 3 verdeutlicht das Strickmuster.
Listing 3
SELECT "Bilder".* , IFNULL( "Titel", '' ) AS "T" , IFNULL( "Autor", '' ) AS "A" FROM "Bilder" WHERE "T" = IFNULL( ( SELECT "Titel" FROM "Filter" ), "T" ) AND "A" = IFNULL( ( SELECT "Autor" FROM "Filter" ), "A" )
Allerdings braucht auch die Tabelle Filter für jedes neue Suchfeld eine weitere Spalte vom gleichen Datentyp wie seine Entsprechung in Bilder, im Beispiel also ein Feld Autor vom Typ VARCHAR. Auch das Unterformular zur Suche benötigt ein weiteres Textfeld, mit dem sich der Autorenname in Filter verändern lässt.
Fazit
Es ist schon etwas frustrierend, wie schnell das Prinzip des “Zusammenklickens” von Datenbankfunktionen in Base an seine Grenzen stößt: Bereits für den Vergleich eines Tabellenfeldes mit dem Wert einer anderen Tabelle fehlt es dem grafischen Abfrage-Editor an Ausdruckskraft. Allerdings mussten wir für die Beispieldatenbank immer noch um eine Größenordnung weniger Code schreiben als für eine vergleichbare Webanwendung in Perl oder PHP.
Jedoch hinterlässt Base insgesamt einen deutlich weniger ausgereiften Eindruck als die LibreOffice-Textverarbeitung. Das zeigt sich auch an häufigen Programmabstürzen, die im schlimmsten Fall sogar die Datenbank korrumpieren. Überlegen Sie es sich gut, ob Sie Base kritische Daten anvertrauen, und nutzen Sie gegebenenfalls zumindest eine externe Datenbank-Engine wie MySQL oder PostgreSQL.
Falls Sie das vorgestellte Beispiel erweitern möchten, finden Sie in den umfassenden und verständlich formulierten offiziellen Handbüchern [2] wertvolle Hilfestellungen. Die zum Programm mitgelieferte Online-Hilfe erweist sich hingegen als weitgehend unbrauchbar.
Infos
[1] LibreOffice Base: http://de.libreoffice.org/product/libreoffice-base/
[2] Deutsche LibreOffice-Handbücher: http://de.libreoffice.org/product/libreoffice-base/





