Einfache Beispiele für SQL-Kommandos

+ andere TechDocs
+ SQL
+ MySQL
+ PostgreSQL
+ SQL mit Java/JDBC
+


Erläuterungen zu SQL-Grundlagen finden Sie in sql.htm.
Hier finden Sie kommentierte einfache Beispiele für SQL-Kommandos.



Inhalt

  1. Installation einer SQL-Datenbank
  2. Laden der Übungstabellen
  3. Einfache SQL-Kommandos anhand der Tabelle "Personen"
  4. Aggregatfunktionen anhand der Tabelle "Speisen"
  5. Joins anhand der Tabelle "Bestellung"
  6. Inner Join, Left Outer Join, Right Outer Join


Installation einer SQL-Datenbank

Bitte verfahren Sie zur Installation Ihrer Datenbank, wie in der zur Datenbank gehörenden Dokumentation beschrieben ist.

Zu MySQL finden Sie für Windows eine kurze Installationsbeschreibung auch unter mysql.htm#InstallationUnterWindows und eine Anleitung zur Anlage einer Database und einer Tabelle unter mysql.htm#CreateDatabase.

Zu PostgreSQL finden Sie für Linux kurze Installationsbeschreibungen und eine Anleitung zur Anlage einer Database und einer Tabelle unter postgresql.htm.



Laden der Übungstabellen

Wenn Sie die folgenden SQL-Kommandos selbst ausprobieren wollen, müssen Sie vorher die drei Beispieltabellen "Personen", "Speisen" und "Bestellung" anlegen.

Bitte laden Sie dafür die Seite sql-commands.sql.htm in Ihren Webbrowser, markieren alles (im Microsoft Internet Explorer z.B. mit "Strg+A"), kopieren alles in den Zwischenspeicher (z.B. mit "Strg+C" oder "Strg+Einfg") und erstellen eine neue Datei "sql-commands.sql", in die Sie alles einfügen (z.B. mit "Strg+V" oder "Umschalt+Einfg"). Bei sehr vielen Datenbanken können Sie diese .sql-Datei an ein mit der Datenbank mitinstalliertes Hilfs- oder Administrationsprogramm übergeben und die enthaltenen SQL-Kommandos so alle in einem Durchgang ausführen (siehe z.B. unter "Ausführen" in mysql.htm). Bei anderen Datenbanken benötigen Sie vielleicht spezielle Hilfs- oder Administrationsprogramme oder müssen eventuell die SQL-Kommandos einzeln ausführen.

Statt über Kommandozeilenprogramme können Sie die SQL-Kommandos natürlich auch über Datenbank-Tools ausführen, zum Beispiel mit SQuirreL.



Einfache SQL-Kommandos anhand der Tabelle "Personen"


SELECT * FROM Personen
idNameAbteilungTelPlzOrt
1GabiSekr100  
2TatianaGF202  
3ManfredGF201  
4IrisMK401  
5RenéPM501  
6ElenaMM301  
7AidarMM301  
8OlegMM301  
9AndreasEntw61052525Heinsberg
10ArthurEntw61252499Baesweiler
11GregorEntw61152351Düren
12MichaelEntw61650859Köln
13NorbertEntw61452134Herzogenrath
14RolandEntw60152134Herzogenrath
15StefanEntw61352062Aachen
16TorstenEntw60152072Aachen
17WernerEntw61552076Aachen
18FAX 101  
19Konferenzraum 700  
"SELECT * FROM ..." zeigt den kompletten Inhalt der genannten Tabelle, allerdings ist die Reihenfolge der Zeilen nicht unbedingt reproduzierbar.

Deshalb sollten normalerweise hinter "ORDER BY" eine oder mehrere Spaltentitel angegeben werden, nach denen sortiert wird, wie es die unteren beiden Beispiele zeigen.

Die untere linke Tabelle ist zuerst nach Abteilungsname sortiert und bei gleichem Abteilungsnamen in zweiter Priorität nach dem Namen.

Ähnlich die untere rechte Tabelle, aber hier ist der Abteilungsname in absteigender Reihenfolge sortiert ("DESC" = descent) und innerhalb der gleichen Abteilung der Name weiterhin in aufsteigender Reihenfolge.

SELECT * FROM Personen ORDER BY Abteilung, Name
idNameAbteilungTelPlzOrt
18FAX 101  
19Konferenzraum 700  
9AndreasEntw61052525Heinsberg
10ArthurEntw61252499Baesweiler
11GregorEntw61152351Düren
12MichaelEntw61650859Köln
13NorbertEntw61452134Herzogenrath
14RolandEntw60152134Herzogenrath
15StefanEntw61352062Aachen
16TorstenEntw60152072Aachen
17WernerEntw61552076Aachen
3ManfredGF201  
2TatianaGF202  
4IrisMK401  
7AidarMM301  
6ElenaMM301  
8OlegMM301  
5RenéPM501  
1GabiSekr100  

SELECT * FROM Personen ORDER BY Abteilung DESC, Name
idNameAbteilungTelPlzOrt
1GabiSekr100  
5RenéPM501  
7AidarMM301  
6ElenaMM301  
8OlegMM301  
4IrisMK401  
3ManfredGF201  
2TatianaGF202  
9AndreasEntw61052525Heinsberg
10ArthurEntw61252499Baesweiler
11GregorEntw61152351Düren
12MichaelEntw61650859Köln
13NorbertEntw61452134Herzogenrath
14RolandEntw60152134Herzogenrath
15StefanEntw61352062Aachen
16TorstenEntw60152072Aachen
17WernerEntw61552076Aachen
18FAX 101  
19Konferenzraum 700  

SELECT Name, Ort FROM Personen WHERE Ort = 'Aachen'
NameOrt
StefanAachen
TorstenAachen
WernerAachen
Statt "SELECT *" (mit Stern) zeigt "SELECT ..., ..." (ohne Stern, mit Spaltennamen) nur die genannten Spalten.
Mit "WHERE" wird eine Bedingung definiert, welche einschränkt, welche Zeilen angezeigt werden sollen.
Bitte beachten: Einige Datenbanken selektieren Case-sensitiv (unter Beachtung der Groß-/Kleinschreibung), andere nicht.

SELECT * FROM Personen WHERE Abteilung = 'Entw' AND (Ort = 'Düren' OR Ort = 'Köln')
idNameAbteilungTelPlzOrt
11GregorEntw61152351Düren
12MichaelEntw61650859Köln
Die "WHERE"-Bedingung kann mit einer Verknüpfung logischer Operationen gebildet werden (hier mit "AND" und "OR").

SELECT * FROM Personen WHERE Abteilung <> 'Entw'
idNameAbteilungTelPlzOrt
1GabiSekr100  
2TatianaGF202  
3ManfredGF201  
4IrisMK401  
5RenéPM501  
6ElenaMM301  
7AidarMM301  
8OlegMM301  
Als Ungleichheitszeichen wird "<>" verwendet.
Einige Datenbanken verstehen zusätzlich auch das in Java übliche "!=", aber "<>" ist standardkonformer.

SELECT * FROM Personen WHERE Ort LIKE '%zog%'
idNameAbteilungTelPlzOrt
13NorbertEntw61452134Herzogenrath
14RolandEntw60152134Herzogenrath
Mit "LIKE" kann eine ungefähre Übereinstimmung gefordert werden.
Das Prozentzeichen ("%") dient dabei als Platzhalter für beliebig viele Zeichen.

SELECT * FROM Personen WHERE Tel LIKE '__0'
idNameAbteilungTelPlzOrt
1GabiSekr100  
9AndreasEntw61052525Heinsberg
19Konferenzraum 700  
Der Unterstrich ("_") dient in "LIKE"-Bedingungen als Platzhalter für genau ein Zeichen.

SELECT * FROM Personen WHERE Plz BETWEEN 52351 AND 52499
idNameAbteilungTelPlzOrt
10ArthurEntw61252499Baesweiler
11GregorEntw61152351Düren
Mit "BETWEEN" kann ein nummerischer Wertebereich definiert werden.

SELECT * FROM Personen
WHERE Abteilung IS NULL

idNameAbteilungTelPlzOrt
18FAX 101  
19Konferenzraum 700  
Mit "IS NULL" (bzw. mit "IS NOT NULL") werden leere Einträge abgefragt.
Achtung, es gibt zweierlei zu beachten:
1.) Leere Strings werden nicht einheitlich behandelt. In einigen Datenbanken (z.B. Oracle) gibt es keine Leerstrings, ein leerer String würde als "NULL"-Wert gespeichert. Aber in anderen Datenbanken (z.B. MySQL) gibt es sowohl "NULL"-Werte als auch leere Strings (mit Länge 0). Um datenbankunabhängig zu programmieren, sollte mit beidem gerechnet werden.
2.) Anders als zum Beispiel bei Java kann es auch bei nummerischen Werten "NULL"-Werte geben. Diese Werte bedeuten nicht die Zahl "0", sondern hier wurde nichts (oder explizit "NULL") eingetragen. Bei der Umwandlung in einen nummerischen Wert ist deshalb eine Sonderbehandlung erforderlich (wenn die Spalte beim Anlegen der Tabelle nicht explizit als "NOT NULL" definiert wurde).

SELECT DISTINCT Abteilung FROM Personen WHERE Abteilung IS NOT NULL
Abteilung
Sekr
GF
MK
PM
MM
Entw
"DISTINCT" kummuliert mehrere Zeilen mit gleichen Spaltenwerten zu einer Zeile.
Man erhält also nur unterschiedliche Einträge, es gibt keine doppelten Einträge.
Hier im Beispiel sind die vielen Zeilen zum Beispiel zur Abteilung "Entw" zu einer Zeile zusammengefasst.

SELECT COUNT(*) FROM Personen WHERE Abteilung = 'Entw'
COUNT(*)
9
"COUNT(*)" zählt die Zahl der Zeilen, die die Bedingung erfüllen.
Ohne WHERE-Bedingung würde gezählt, wie viele Zeilen die Tabelle beinhaltet.
Allerdings sind solche Zahlen mit Vorsicht zu gebrauchen, da wenige Sekunden später vielleicht eine andere Anwendung eine zusätzliche Zeile hinzugefügt oder eine andere entfernt haben könnte.

SELECT Abteilung, COUNT(*) "Anzahl Personen pro Abteilung" FROM Personen GROUP BY Abteilung
AbteilungAnzahl Personen
pro Abteilung
 2
Entw9
GF2
MK1
MM3
PM1
Sekr1
"GROUP BY" gruppiert die Ergebniszeilen. Ähnlich wie bei DISTINCT werden Zeilen mit gleichem Gruppierungswert zu einer Zeile zusammengefasst.
Bei "GROUP BY"-Kommandos machen hinter "SELECT" nur Tabellenspalten Sinn, die entweder in der Gruppierungsbedingung enthalten sind (im Beispiel die Spalte "Abteilung") oder Aggregatfunktionen (im Beispiel "COUNT(*)").
Hier im Beispiel gibt "COUNT(*)" an, wie viele Zeilen pro Gruppierung zusammengefasst wurden, was gleichbedeutend ist mit der Anzahl Personen pro Abteilung.
Wie das Beispiel zeigt, kann die Spaltenüberschrift durch einen direkt nach dem Spaltennamen (bzw. der Aggregatfunktion) folgenden in doppelten Hochkommas ("Gänsefüsschen") eingeschlossenen Text ("...") ersetzt werden, der dann als Spaltentitel gilt, wodurch die Verständlichkeit erhöht werden kann. Leider weicht die Syntax zur Spaltentitelübersetzung bei einigen Datenbanken etwas von der gezeigten ab.

SELECT Abteilung, COUNT(*) FROM Personen GROUP BY Abteilung HAVING COUNT(*) >= 3
AbteilungCOUNT(*)
Entw9
MM3
Die mit "GROUP BY" ermittelte Menge an Zeilen kann eingeschränkt werden durch eine "HAVING"-Bedingung.


Aggregatfunktionen anhand der Tabelle "Speisen"


SELECT * FROM Speisen ORDER BY id
idGerichtPreisZutaten
101Pizza Diabolo5.5Teufelsohren
102Pizza Vulkano6Teig, Käse, Vesuvtomaten
103Pizza Feuro6.5Pepperoni
104Lasagno6Nudeln, Hackfleisch
105Salat Eskimo4.5Eiswürfel
Die Tabelle "Speisen" ist unsere zweite Beispieltabelle.
Die beiden Tabellen "Personen" und "Speisen" werden später über die Tabelle "Bestellung" verknüpft.

SELECT MIN(PREIS), MAX(PREIS), AVG(PREIS), SUM(PREIS), COUNT(PREIS) FROM Speisen
MIN(PREIS)MAX(PREIS)AVG(PREIS)SUM(PREIS)COUNT(PREIS)
4.56.55.728.55
"MIN()", "MAX()", "AVG()", "SUM()" und "COUNT()" sind sogenannte Aggregatfunktionen. Sie fassen Werte aus mehreren Zeilen zu einem Wert zusammen.


Joins anhand der Tabelle "Bestellung"


SELECT * FROM Bestellung ORDER BY id
idid_Kundeid_Speise
19105
211103
312103
414103
515101
615102
715103
816104
917103
Die Mitarbeiter einer Firma bestellen Gerichte beim Italiener.
Da die Kundendaten bereits aus früheren und für zukünftige Bestellungen gesondert erfasst wurden und die Speisen natürlich ebenfalls in einer Tabelle abgelegt sind, genügt für die Aufnahme der Bestellung eine Tabelle, die lediglich Verweise auf die Kunden und Speisen enthält.
"id_Kunde" und "id_Speise" sind sogenannte "Foreign Keys" (Fremdschlüssel), da sie Werte enthalten, die in einer anderen Tabelle als "Primary Key" (Primärschlüssel) definiert sind und so eindeutig Zeilen in der anderen Tabelle spezifizieren.
"id_Kunde" enthält nur "id"-Werte aus der Tabelle "Personen" und "id_Speise" enthält nur "id"-Werte aus der Tabelle "Speisen".
Die Tabelle ist datenbanktechnisch so korrekt und enthält keinerlei redundanten Daten, allerdings ist sie für den Menschen so schwer verständlich, weshalb wir die Darstellung erweitern wollen.

Die untere Tabelle zeigt einen Join dreier Tabellen, der eine korrekte Verknüpfung zwischen den drei Tabellen bildet, allerdings sehr unübersichtlich, da er einfach alle Spalten anzeigt.

SELECT * FROM Bestellung, Personen, Speisen
WHERE id_Kunde = Personen.id AND id_Speise = Speisen.id

idid_Kundeid_SpeiseidNameAbteilungTelPlzOrtidGerichtPreisZutaten
191059AndreasEntw61052525Heinsberg105Salat Eskimo4.5Eiswürfel
21110311GregorEntw61152351Düren103Pizza Feuro6.5Pepperoni
31210312MichaelEntw61650859Köln103Pizza Feuro6.5Pepperoni
41410314RolandEntw60152134Herzogenrath103Pizza Feuro6.5Pepperoni
51510115StefanEntw61352062Aachen101Pizza Diabolo5.5Teufelsohren
61510215StefanEntw61352062Aachen102Pizza Vulkano6Teig, Käse, Vesuvtomaten
71510315StefanEntw61352062Aachen103Pizza Feuro6.5Pepperoni
81610416TorstenEntw60152072Aachen104Lasagno6Nudeln, Hackfleisch
91710317WernerEntw61552076Aachen103Pizza Feuro6.5Pepperoni

SELECT Name, Gericht, Preis FROM Bestellung, Personen, Speisen
WHERE id_Kunde = Personen.id AND id_Speise = Speisen.id ORDER BY Name

NameGerichtPreis
AndreasSalat Eskimo4.5
GregorPizza Feuro6.5
MichaelPizza Feuro6.5
RolandPizza Feuro6.5
StefanPizza Diabolo5.5
StefanPizza Vulkano6
StefanPizza Feuro6.5
TorstenLasagno6
WernerPizza Feuro6.5
Anders als obige Tabelle zeigt die links abgebildete Tabelle nur die relevanten Spalten.
Ein Join kann zwei oder auch sehr viele Tabellen verknüpfen.
Wichtig:
Ein Join über n Tabellen benötigt n-1 Verknüpfungsbedingungen zwischen den Tabellen.
Für unsere drei Tabellen "Bestellung", "Personen" und "Speisen" benötigen wir die beiden Verknüpfungsbedingungen "id_Kunde = Personen.id" und "id_Speise = Speisen.id".
Beachten:
Der Spaltenname "id" kommt in den beiden Tabellen "Personen" und "Speisen" vor und ist deshalb nicht eindeutig. In allen nicht eindeutigen Fällen muss der Tabellenname durch einen Punkt abgetrennt vorangestellt werden (im Beispiel: "Personen.id" und "Speisen.id"). Der Einfachheit halber empfiehlt es sich, bei Joins den Tabellennamen immer voranzustellen.

SELECT Name, COUNT(*), SUM(Preis) FROM Bestellung, Personen, Speisen
WHERE id_Kunde = Personen.id AND id_Speise = Speisen.id
GROUP BY Name ORDER BY Name

NameCOUNT(*)SUM(Preis)
Andreas14.5
Gregor16.5
Michael16.5
Roland16.5
Stefan318
Torsten16
Werner16.5
Dieser Join ermittelt, wer wie viele Gerichte bestellt hat und wie viel jeder einzelne bezahlen muss.

SELECT Gericht, COUNT(*), SUM(Preis) FROM Bestellung, Speisen
WHERE id_Speise = Speisen.id
GROUP BY Gericht ORDER BY Gericht

GerichtCOUNT(*)SUM(Preis)
Lasagno16
Pizza Diabolo15.5
Pizza Feuro532.5
Pizza Vulkano16
Salat Eskimo14.5
Dieser Join ermittelt für den Pizzabäcker, weches Gericht wie oft geliefert werden muss.


Inner Join, Left Outer Join, Right Outer Join

CREATE TABLE A ( id INT, sa VARCHAR(8) );
CREATE TABLE B ( id INT, sb VARCHAR(8) );
INSERT INTO A VALUES ( 1, 'A1' );
INSERT INTO A VALUES ( 2, 'A2' );
INSERT INTO A VALUES ( 5, 'A5' );
INSERT INTO A VALUES ( null, 'A6' );
INSERT INTO B VALUES ( 1, 'B1' );
INSERT INTO B VALUES ( 2, 'B2' );
INSERT INTO B VALUES ( 8, 'B8' );
INSERT INTO B VALUES ( null, 'B9' );
Zur Erläuterung der Unterschiede zwischen den Join-Typen "Inner Join", "Left Outer Join" und "Right Outer Join" werden mit den links stehenden SQL-Kommandos zwei besonders kleine Tabellen neu angelegt.

Select * from A, B where A.id = B.id;
oder
Select * from A join B on A.id = B.id;
idsaidsb
1A11B1
2A22B2
"Inner Join":
Beide SQL-Kommandos führen zum identischen Ergebnis. Die zweite Form wird bevorzugt, weil die Join-Bedingung von anderen Where-Bedingungen abgesetzt ist.
Das Ergebnis enthält nur Datensätze, bei denen in beiden Tabellen die Werte der Join-Bedingung gefüllt und gleich sind.

Select * from A left join B on A.id = B.id;
idsaidsb
1A11B1
2A22B2
5A5<null><null>
<null>A6<null><null>
"Left Outer Join":
Das Ergebnis enthält alle Datensätze der "linken" Tabelle A, auch dann wenn es in der "rechten" Tabelle B keine korrespondierenden Einträge gibt.
Normalerweise wird die Anzahl der resultierenden Datensätze also von der "linken" Tabelle bestimmt. Aber beachten Sie: Falls die für die Join-Bedingung verwendete Spalte aus der "rechten" Tabelle nicht unique ist, wenn also Werte mehrfach vorkommen können, dann ist die Anzahl der resultierenden Datensätze höher.

Select * from A right join B on A.id = B.id;
idsaidsb
1A11B1
2A22B2
<null><null>8B8
<null><null><null>B9
"Right Outer Join":
Das Ergebnis enthält alle Datensätze der "rechten" Tabelle B, auch dann wenn es in der "linken" Tabelle A keine korrespondierenden Einträge gibt.
Wie leicht erkannt werden kann, liefert "A left join B" dasselbe Ergebnis wie "B right join A".

Ausführlichere Erläuterungen zu Joins finden Sie unter: Einführung in SQL: OUTER JOIN, Visual Representation of SQL Joins und SQL-Joins-Grafik.



Weitere Themen: andere TechDocs | SQL-Themen | SQL-Grundlagen | Vererbung und Polymorphie | SQL mit Java | O/R-M mit Hibernate | MySQL | PostgreSQL
© 1998-2007 Torsten Horn, Aachen