Warum noch ein Access-Buch?
Für wen ist das Buch?
Jetzt bestellen
+ direkter Download des eBooks!
Nur EUR 59,95!
Fehler gefunden?
Bitte melden!
Wünsche an das Buch?
Her damit!
Was denken die Leser über dieses Buch?
Lesen Sie aktuelle Rezensionen!
Kapitel des noch nicht veröffentlichten Buchs zum Downloaden, Probelesen und Kommentieren
Beispieldatenbanken
Zusätzliches Material

Das Buch im HTML-Format

Für unbestimmte Zeit bieten Addison-Wesley und André Minhorst den kompletten Inhalt des Buchs als Download an. Schauen Sie rein und informieren Sie sich über den Inhalt! Und wenn Ihnen das Buch nützlich erscheint und Sie glauben, dass Sie etwas gelernt haben oder durch das Gelesene sogar etwas Zeit und somit Geld bei Ihrer Arbeit einsparen konnten, können Sie sich ja beim Autor und beim Verlag revanchieren - beispielsweise durch den Kauf dieses Buchs.

Am schönsten wäre es natürlich, wenn Sie das Buch direkt hier bestellen - Sie erhalten das Buch dann direkt vom Verlag, und der Autor und Verlag haben dann noch mehr davon, als wenn Sie es anderswo kaufen.

Danke für Ihr Interesse!

8.3.8 WHERE, GROUP BY, HAVING und ORDER BY im Überblick

8.3.9 Verknüpfen von Tabellen in Abfragen

Wenn Sie mehrere Tabellen im FROM-Bereich als Datenherkunft eines SQL-Ausdrucks angeben, werden diese von der ACE-Engine als völlig losgelöst von jeglichen zuvor angelegten Beziehungen zwischen den Tabellen betrachtet.

Manuelles Hinzufügen einer Verknüpfung

Sie können durchaus eine 1:n-Beziehung mit referentieller Integrität zwischen Tabellen wie tblProjekte und tblMitarbeiter im Beziehungsfenster angelegt haben - sobald Sie diese beiden Tabellen in der folgenden Form in einem SQL-Ausdruck angeben, ist alles vergessen:

SELECT tblProjekte.ProjektID, tblMitarbeiter.MitarbeiterID FROM tblProjekte, tblMitarbeiter;

Die Abfrage-Entwurfsansicht hat da ein etwas besseres Gedächtnis. Sie erkennt direkt bestehende Beziehungen und zeigt diese auch an, wie in Abbildung 8.11. Allerdings können Sie auch diese Möglichkeit ausschalten:

Dazu deaktivieren Sie auf der Registerseite Objekt-Designer des Access-Optionen-Dialogs (Office-Menü, Schaltfläche Access-Optionen) die Eigenschaft AutoVerknüpfung aktivieren.

Ein Wechsel von hier aus in die SQL-Ansicht zeigt, welchen zusätzlichen Code die Festlegung einer Beziehung zwischen zwei Tabellen mit sich bringt:

Abbildung 8.11: Die Abfrage-Entwurfsansicht übernimmt bestehende Beziehungen nach dem Hinzufügen von verknüpften Tabellen

SELECT tblMitarbeiter.MitarbeiterID, tblProjekte.ProjektID
FROM tblMitarbeiter INNER JOIN tblProjekte
ON tblMitarbeiter.MitarbeiterID = tblProjekte.MitarbeiterID;

Es gibt noch eine weitere Möglichkeit, zwei Tabellen innerhalb eines SQL-Ausdrucks zu verknüpfen. Dabei erfolgt die Verknüpfung im WHERE-Teil der Abfrage:

SELECT tblMitarbeiter.MitarbeiterID, tblProjekte.ProjektID
FROM tblMitarbeiter, tblProjekte
WHERE tblMitarbeiter.MitarbeiterID = tblProjekte.MitarbeiterID;

Diese Variante schreibt sich zwar etwas kürzer, kann aber keine OUTER JOIN-Verknüpfungen abbilden - mehr zu dieser Verknüpfungsart später. Noch gravierender ist der Nachteil, dass das Abfrageergebnis nicht aktualisiert werden kann - das zeigt ein Blick auf die Datenblatt-Ansicht einer solchen Abfrage (siehe Abbildung 8.12). Dort findet sich keine Möglichkeit, einen neuen Datensatz anzulegen, und auch eine Änderung der enthaltenen Daten ist nicht möglich.

Abbildung 8.12: WHERE-Verknüpfungen sind nicht aktualisierbar

Im Entwurfsfenster einer solchen Abfrage erscheint übrigens keine Verknüpfungslinie, die WHERE-Bedingung wird wie üblich im Entwurfsraster angezeigt (siehe Abbildung 8.13).

Abbildung 8.13: Beziehung per Kriterium

Aufbau von Verknüpfungen ( INNER JOIN)

Einfache Verknüpfungen zwischen zwei Tabellen definiert man in SQL folgendermaßen:

INNER JOIN
ON . = .;

Kommen weitere Tabellen hinzu, setzt man den Ausdruck für die erste Verknüpfung in Klammern und behandelt ihn für die Erstellung der zweiten Verknüpfung wie eine einzige Tabelle. Die neue Verknüpfung baut man einfach um den bestehenden Ausdruck herum wie im folgenden Beispiel (neue Teile fett gedruckt):

INNER JOIN (
INNER JOIN
ON . = .)
ON .;

Beispiel: Die klassische m:n-Beziehung zwischen Bestellungen, Bestelldetails und Artikeln enthält zwei INNER JOIN-Verknüpfungen (siehe Abbildung 8.14).

Der entsprechende SQL-Ausdruck sieht folgendermaßen aus:

SELECT tblBestelldetails.ArtikelID, tblArtikel.Artikel, tblBestelldetails.Anzahl, tblBestellungen.Lieferdatum FROM tblBestellungen

INNER JOIN (
    tblArtikel INNER JOIN tblBestelldetails
    ON tblArtikel.ArtikelID = tblBestelldetails.ArtikelID
) ON tblBestellungen.BestellungID = tblBestelldetails.BestellungID;

Abbildung 8.14: Abfrage mit zwei Verknüpfungen

Weitere Verknüpfungsarten

Neben den INNER JOINS, die alle Datensätze ausgeben, bei denen die Inhalte des Verknüpfungsfeldes gleich sind, gibt es noch weitere Verknüpfungsarten.

Ein OUTER JOIN liefert alle Datensätze der ersten Tabelle zurück und nur die Datensätze der zweiten Tabelle, die mit einem Datensatz der ersten Tabelle verknüpft sind. OUTER JOIN-Abfragen treten als LEFT OUTER JOIN und RIGHT OUTER JOIN auf. LEFT beziehungsweise RIGHT legt dabei fest, ob alle Datensätze von der links vom Schlüsselwort JOIN stehenden Tabelle ausgegeben werden oder von der rechts davon stehenden Tabelle.

Beispiel: Der folgende SQL-Ausdruck soll alle Mitarbeiter und ihre Projekte ausgeben, aber auch die Mitarbeiter berücksichtigen, denen kein Projekt zugeordnet ist.

SELECT Nachname & ", " & Vorname AS Mitarbeiter, tblProjekte.Projekt
FROM tblMitarbeiter LEFT JOIN tblProjekte
ON tblMitarbeiter.MitarbeiterID=tblProjekte.MitarbeiterID;

Abbildung 8.15 zeigt das Ergebnis dieses SQL-Ausdrucks.

Für die Verwendung von OUTER JOIN-Verknüpfungen gibt es zwei wichtige Regeln: Die rechte Tabelle eines LEFT OUTER JOIN kann nicht mit anderen Tabellen per INNER JOIN verknüpft werden und kann nicht die linke Tabelle eines anderen RIGHT OUTER JOIN oder die rechte Tabelle eines LEFT OUTER JOIN sein. Sie erhalten sonst die Fehlermeldung »Abfrage konnte nicht ausgeführt werden, da sie mehrdeutige Inklusionsverknüpfungen enthält«.

Abbildung 8.15: Ergebnis einer Abfrage mit LEFT OUTER JOIN-Verknüpfung

Rekursive Verknüpfungen lassen sich ebenfalls mit SQL realisieren. Allerdings gibt es dafür kein spezielles Sprachkonstrukt. Statt dessen verwenden Sie einfach einen kleinen Trick.

Zum Herstellen einer Beziehung kommen Sie definitiv nicht daran vorbei, zwei Tabellen miteinander zu verknüpfen - es ist aber nicht verboten, zweimal die gleiche Tabelle zu nehmen. Sie müssen nur eine der Tabellen - wie weiter oben erläutert - mit dem AS-Schlüsselwort umbenennen.

Das folgende Beispiel zeigt, wie es funktioniert. Das Abfrageergebnis finden Sie in Abbildung 8.16.

SELECT tblMitarbeiter.MitarbeiterID, tblMitarbeiter.Nachname & ", " & tblMitarbeiter.Vorname AS Mitarbeiter, tblVorgesetzte.Nachname & ", " & tblVorgesetzte.Vorname AS Vorgesetzter FROM tblMitarbeiter INNER JOIN tblMitarbeiter AS tblVorgesetzte ON tblMitarbeiter.VorgesetzterID = tblVorgesetzte.MitarbeiterID;

In der Bedingung für die Herstellung der Verknüpfung (den ON-Abschnitt) haben die bisherigen Beispiele immer das Gleichheitszeichen als Vergleichsoperator verwendet. Sie können auch andere Vergleichsoperatoren wie >, >=, <, <=, <> oder BETWEEN einsetzen. Der Anteil von SQL-Ausdrücken mit anderen Vergleichsoperatoren als dem Gleichheitszeichen ist aber relativ gering.

Abbildung 8.16: Beispiel für die Ausgabe rekursiv verknüpfter Daten

Unterabfragen

Weiter oben in Abschnitt 8.3.4 unter »Vergleiche mit Zahlen« haben Sie bereits erfahren, dass man mit dem IN-Operator Vergleiche von Feldinhalten mit einer Gruppe von Werten vornehmen kann. Es wäre sehr unpraktisch, wenn man die Vergleichswerte immer manuell eintragen müsste. Unterabfragen lösen dieses und andere Probleme auf elegante Weise: Sie treten als Abfrage in der Abfrage auf und liefern so die Vergleichswerte für Kriterienausdrücke. Dabei können diese entweder nur einen einzelnen Wert als Vergleichswert zurückliefern oder eine Gruppe von Werten eines Feldes, das mit dem IN-Operator untersucht wird.

Beispiel für eine Unterabfrage, die einen Vergleichswert liefert: Der folgende SQL-Ausdruck liefert alle Produkte zurück, deren Preis über dem durchschnittlichen Preis aller Produkte liegt.

SELECT ProduktID, Produkt, Preis
FROM tblProdukte
WHERE Preis > (SELECT Avg(Preis) FROM tblProdukte);

Behandlung doppelter Datensätze in Ergebnissen von SQL-Ausdrücken

SQL-Ausdrücke, die mehrere Abfragen enthalten, liefern oft doppelte Daten zurück. Das ist zum Beispiel der Fall, wenn Sie eine Projekt- und eine Kundentabelle verknüpfen und alle Kunden ausgeben möchten, denen ein aktuelles Projekt zugewiesen ist:

SELECT tblKunden.KundeID, tblKunden.Firma
FROM tblKunden INNER JOIN tblProjekte
ON tblKunden.KundeID = tblProjekte.KundeID;

Wenn es zwei oder mehr Projekte im Auftrag eines Kunden gibt, wird dieser Kunde im Ergebnis auch mehrfach angezeigt, wie Abbildung 8.17 zeigt.

In dieser Abfrage wird implizit das Prädikat ALL für den SELECT-Teil der Abfrage verwendet. Das bedeutet, dass alle Datensätze des Ergebnisses ausgegeben werden. Der folgende SQL-Ausdruck mit dem ALL-Prädikat erfüllt die gleiche Funktion:

SELECT ALL tblKunden.KundeID, tblKunden.Firma FROM tblKunden INNER JOIN tblProjekte ON tblKunden.KundeID = tblProjekte.KundeID;

Abbildung 8.17: Mehrfache Anzeige von Kunden

Wenn Sie gleiche Datensätze nicht doppelt anzeigen möchten, können Sie eines der Prädikate DISTINCT oder DISTINCTROW verwenden. Jedes dieser Prädikate geben Sie unmittelbar hinter dem SELECT-Schlüsselwort an.

Mit dem DISTINCT-Prädikat sorgen Sie dafür, dass das Abfrageergebnis jede Kombination der ausgegebenen Daten nur einmal anzeigt. Dieses Prädikat hat die gleiche Wirkung wie das Einstellen der Eigenschaft Keine Duplikate (in Visual Basic: UniqueValues) auf den Wert Ja (True).

Im folgenden Beispiel werden also tatsächlich nur die Firmen angezeigt, die mit einem Projekt verknüpft sind:

SELECT DISTINCT tblKunden.KundeID, tblKunden.Firma
FROM tblKunden INNER JOIN tblProjekte
ON tblKunden.KundeID = tblProjekte.KundeID;

Das DISTINCTROW-Prädikat bringt in vielen Fällen das gleiche Ergebnis wie das DISTINCT-Prädikat. Es bezieht sich nicht nur auf die im Abfrageergebnis angezeigten Felder, sondern auf die gesamte Datenherkunft der Abfrage. Das Prädikat hat die gleiche Wirkung wie das Einstellen der Eigenschaft Eindeutige Datensätze (UniqueRecords) auf den Wert Ja (True).

Ein weiterer großer Unterschied zwischen DISTINCT und DISTINCTROW ist, dass das Ergebnis einer Abfrage mit dem DISTINCTROW-Prädikat aktualisierbar ist. Außerdem ist DISTINCTROW eine Spezialität von Access-SQL, die nicht dem SQL-Standard entspricht. Ein gutes Verständnis für den Unterschied liefert folgendes Beispiel. Die Tabelle aus Abbildung 8.18 enthält Mitarbeiterdaten. Die folgenden beiden Abfragen sollen nur die Vornamen der Mitarbeiter ausgeben und damit zeigen, wie sich die beiden Prädikate auswirken.

Abbildung 8.18: Beispieltabelle für den Einsatz von DISTINCT und DISTINCTROW

Die erste Abfrage verwendet das DISTINCT-Prädikat. Sie liefert das Ergebnis des linken Fensters in Abbildung 8.19 - der Vorname Bernd wird nur einfach ausgegeben, obwohl er zweimal in der zugrunde liegenden Tabelle enthalten ist. Der Grund ist, dass DISTINCT nur die ausgegebenen Felder auf Duplikate untersucht.

SELECT DISTINCT Vorname FROM tblMitarbeiter;

Die zweite Abfrage mit dem DISTINCTROW-Prädikat gibt beide Mitarbeiter mit dem Vornamen Bernd aus. Diese Abfrage untersucht die ganze Tabelle tblMitarbeiter. Deren Datensätze sind natürlich alle verschieden, da zumindest der Primärschlüssel einen eindeutigen Wert enthält.

SELECT DISTINCTROW Vorname FROM tblMitarbeiter;

Die ersten x oder die ersten x Prozent der Datensätze ausgeben

Wenn Sie das Ergebnis einer Abfrage dahingehend einschränken möchten, dass nur die ersten x Datensätze oder die ersten x Prozent der Datensätze ausgegeben werden sollen, verwenden Sie das TOP-Prädikat. Die folgende Beispielabfrage liefert die drei teuersten Produkte einer Tabelle zurück:

SELECT TOP 3 ProduktID, Produkt, Preis
FROM tblProdukte
ORDER BY Preis;

Abbildung 8.19: Ergebnisse der DISTINCT- und der DISTINCTROW-Version einer Abfrage

Wichtig ist bei der Verwendung des TOP-Prädikats natürlich die Sortierung der Datensätze nach dem gewünschten Kriterium. Der nächste SQL-Ausdruck ermittelt die teuersten zehn Prozent der Produkte:

SELECT TOP 10 PERCENT ProduktID, Produkt, Preis
FROM tblProdukte
ORDER BY Preis;

Die Prozent-Auswahl gibt »angebrochene« Datensätze mit aus - wenn Sie also zehn Prozent von 21 Produkten ausgeben möchten, erhalten Sie drei Datensätze als Ergebnis.

Parameter verwenden

Wenn Sie eine Abfrage mit Parametern verwenden möchten, wie es auch in der Abfrage-Entwurfsansicht in Abbildung 8.20 möglich ist, reicht es aus, die Parameter wie in der Entwurfsansicht in eckigen Klammern als Kriterium anzugeben:

SELECT MitarbeiterID, Vorname, Nachname
FROM tblMitarbeiter
WHERE Vorname=[Vorname eingeben];

Sie können zusätzlich die PARAMETERS-Klausel verwenden, um einen Datentyp für die Parameter festzulegen. Sie beginnt mit dem Schlüsselwort PARAMETERS und enthält eine durch Kommata getrennte Liste von Wertepaaren, die aus dem in eckigen Klammern gefassten Parameternamen und dem Datentyp bestehen. Das folgende Beispiel zeigt die vorherige Abfrage mit der PARAMETERS-Auflistung:

PARAMETERS [Vorname eingeben] STRING;
SELECT MitarbeiterID, Vorname, Nachname

FROM tblMitarbeiter
WHERE Vorname=[Vorname eingeben];

Abbildung 8.20: Abfrage mit Parameter in der Entwurfsansicht

Die Verwendung des PARAMETERS-Schlüsselworts macht nur Sinn, wenn Sie die Eingabe eines Wertes mit dem richtigen Datentyp erzwingen möchten. In der Regel sollten solche Validierungen aber bereits im Code erfolgen und nicht auf Abfrage-Ebene festgelegt werden.

Zusammenfassen von Abfrageergebnissen mit UNION

Das UNION-Schlüsselwort von SQL ermöglicht das Zusammenfassen der Ergebnisse mehrerer SELECT-Anweisungen. Damit können Sie beispielsweise die Adressen aus einer Mitarbeiter- und einer Kundentabelle in einen Topf werfen, um eine Verteilerliste für Weihnachtskarten zu erstellen.

Der Einsatz von UNION ist ganz einfach: Sie fassen damit zwei Abfragen zusammen, indem Sie zwei oder mehr Abfragen mit diesem Schlüsselwort verbinden:

Abfrage1 UNION Abfrage2 [UNION Abfrage 3 [...]]

Voraussetzung für den Einsatz einer UNION-Abfrage ist, dass alle beteiligten Abfragen die gleiche Anzahl Felder aufweisen.

Der Vorteil von UNION-Abfragen ist, dass auch Daten zusammengeführt werden können, die in den einzelnen Tabellen in unterschiedlicher Form auftreten. Das folgende Beispiel zeigt, wie Sie Vorname und Nachname der Mitarbeitertabelle zusammensetzen und mit den in einem einzigen Feld gespeicherten Namen des Ansprechpartners von Kunden zusammenführen können:

SELECT Vorname & " " & Nachname AS Empfaenger FROM tblMitarbeiter
UNION
SELECT Ansprechpartner FROM tblKunden;

Wenn Sie für das Ergebnis einer UNION-Abfrage eine Sortierung vornehmen möchten, müssen Sie diese im Anschluss an die letzte Abfrage angeben. Sortierkriterien in den vorherigen Abfragen werden nicht berücksichtigt.

Als Feldname des Abfrageergebnisses verwendet Access immer den in der ersten Abfrage angegebenen Feldnamen.

N-Abfragen können nicht in der Entwurfsansicht für Abfragen angelegt werden.

Wenn Sie alle Felder einer Abfrage oder Tabelle in einer UNION-Abfrage verwenden möchten, müssen Sie diese nicht alle im Quellcode angeben. Es reicht die Sternchen(*)-Syntax: SELECT * FROM tblMitarbeiter. Aber auch diese Schreibweise können Sie noch abkürzen: TABLE tblMitarbeiter liefert genauso alle Felder der Tabelle zurück. Diese Syntax können Sie übrigens auch für Abfragen verwenden. Außerdem ist der Einsatzbereich dieser Abkürzung nicht auf UNION-Abfragen beschränkt.

Nächster Abschnitt:

8.3.10 Zugriff auf externe Datenquellen

© 2006-2008 André Minhorst Alle Rechte vorbehalten.