Datenbank/SQL-Grundlagen

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Dieses Kapitel ist eine kurze Einführung in die Syntax von SQL (Structured Query Language) zur Bearbeitung von relationalen Datenbanken. Es ist an kein konkretes Datenbankmanagementsystem gebunden. Die meisten Abfragen funktionieren in allen Datenbankmanagementsystemem (DBMS) gleich oder zumindest ähnlich. Erst bei den unterstützten Datentypen (SQLite kennt beispielsweise nur vier, was für die meisten Anwendungsfälle ausreicht, MySQL hingegen Dutzende) und eingebauten Funktionen wie Volltextsuche oder Datumsformatierung wird es dann meist speziell. Dort sollten Sie im Zweifelsfall das Handbuch des entsprechenden Systems konsultieren.

Die Bezeichnung SQL bezieht sich auf das englische Wort query (englisch für Abfrage). Mit Abfragen werden die in einer Datenbank gespeicherten Daten abgerufen oder verändert und dem Benutzer oder einer Anwendersoftware zur Verfügung gestellt.

Das Ergebnis einer Abfrage sieht wiederum aus wie eine Tabelle und kann oft auch wie eine Tabelle angezeigt, bearbeitet und weiterverwendet werden.

Dieser Artiken möchte die grundlegenden Befehle und Begriffe erklären.

Vorbereitung

Wenn Sie bereits über ein installiertes DBMS verfügen, können Sie den ersten Unterabschnitt überspringen.

Einrichten eines DBMS

Um die hier gezeigten Abfragen ausführen zu können, benötigen Sie ein DBMS (Datenbankmanagementsystem). Das kann ein SQL Server sein (z.B. PostgreSQL oder MariaDB) oder eine Datenbankbibliothek wie SQLite.

  1. Falls Sie einen eigenen Webspace haben, verfügt dieser möglicherweise über eine Datenbank und phpmyadmin (ein grafisches Werkzeug zum Administrieren der Datenbank, in dem Sie auch direkt SQL-Befehle eingeben können).
  2. Falls Sie das Paket XAMPP installiert haben, um einen lokalen Webserver auf ihrem PC zur Verfügung zu haben, verfügen Sie bereits mit dem zu MySQL kompatiblen MariaDB über ein funktionsfähiges Datenbanksystem und mit phpMyAdmin über ein Zugriffstool.
  3. Sie können MariaDB auch direkt installieren und erhalten dann HeidiSQL als Zugriffsoberfläche dazu
  4. DB Browser for SQLite ist ein grafisches Werkzeug zum Bearbeiten von SQLite-Datenbanken und unter Windows, Linux und macOS lauffähig. Eine SQLite-Datenbank besteht aus einer einfachen Datei und eignet sich daher gut zum Experimentieren – Löschen und Sichern eines bestimmten Stands der Datenbank stellen kein Problem dar.
    Das „Lite“ im Namen von SQLite bezieht sich übrigens auf den geringen Ressourcenverbrauch und die einfache Administrierbarkeit, weniger auf den Funktionsumfang in Bezug auf das Verständnis von SQL.
  5. Wer es lieber direkt auf der Kommandozeile mag, kann das Kommandozeilenwerkzeug von SQLite verwenden.

Angesichts der Vielfalt an DBMS und Tools können wir leider nicht auf die Details zum Umgang mit diesen Programmen eingehen.

Testdaten

SQL-Beispiel

Dieses Bild zeigt ein so genanntes „Entity-Relationship“ Modell eines Datenbestandes. Entitäten sind die Dinge, die in der Datenbank gespeichert werden, und Relationen sind die Beziehungen zwischen den Entitäten. Jedes Rechteck steht für einen Entitätstyp, also Dinge, die sich gleichartig beschreiben lassen. Die Ovale daran sind die Attribute, die Eigenschaften, die ein Ding dieses Typs aufweist. Alle Entitäten eines Entitätstyps werden durch den gleichen Satz an Attributen beschrieben: Jeder Student hat eine Matrikelnummer und einen Namen, jede Vorlesung eine Vorlesungsnummer und einen Titel, jeder Professor eine Personalnummer und einen Namen. Zwischen den Entitäten bestehen Beziehungen. Auch hier gibt es verschiedene Typen. Ein Professor hält eine oder mehrere Vorlesungen, jede Vorlesung wird aber von genau einem Professor gehalten. Es ist eine eins-zu-N Beziehung. Zwischen Student und Vorlesung besteht eine m:n Beziehung: Ein Student hört mehrere Vorlesungen, und jede Vorlesung wird von mehreren Studenten gehört.

Relationen:
Student
MatrNr Name
26120 Fichte
25403 Jonas
27103 Fauler
hört
MatrNr VorlNr
25403 5001
26120 5001
26120 5045
Vorlesung
VorlNr Titel PersNr
5001 ET 15
5022 IT 12
5045 DB 12
Professor
PersNr Name
12 Wirth
15 Tesla
20 Urlauber

Entitäten und ihre Attribute lassen sich 1:1 auf Zeilen und Spalten von Tabellen abbilden. Jeder Entitätstyp wird in einer eigenen Tabelle gespeichert. Die Entitäten sind Zeilen dieser Tabelle, und jedes Attribut bekommt eine eigene Spalte.

Das Beispiel zeigt je eine Tabelle für Professoren, für Vorlesungen und für Studenten. Eine 1:N Beziehung lässt sich so abbilden, dass man in den Entitäten der N-Seite einen Schlüssel speichert, der zur Entität der 1-Seite gehört. Die Vorlesung-Tabelle enthält deshalb pro Zeile die PersNr des Professors, der diese Vorlesung hält. Bei einer M:N Beziehung ist es schwieriger. Relationale Datenbanken können in einer Zeile keine Listen von Werten speichern. Darum wird die Beziehung über eine Beziehungstabelle hergestellt, die für jede Paarung die Schlüsselwerte der beiden Entitäten enthält. Oft ist es auch so, dass die Beziehungstabelle noch weitere Attribute enthält, die die Beziehung näher beschreiben. Es könnte beispielsweise die Personalnummer des Tutors sein, der einen Studenten bei einer bestimmten Vorlesung betreut.

Abfragen

Einfaches Lesen einer Tabelle mit SELECT und FROM

Um Tabelleninhalte einer relationalen Datenbank zu lesen, verwendet man den SELECT Befehl. Dieser besteht aus mehreren, in ihrer Reihenfolge festgelegten Teilen, auch Klauseln genannt. Jede Klausel beginnt mit einem Schlüsselwort.

Im einfachsten Fall besteht der SELECT Befehl aus einer SELECT- und einer FROM-Klausel:

SELECT *
FROM Student;

Die FROM-Klausel benennt eine oder auch mehrere Tabellen, deren Inhalte gelesen werden sollen. In der SELECT-Klausel wird aufgelistet, welche Spalten dieser Tabellen auszugeben sind. Möchte man alle Spalten haben, kann man für manuelle Auswertungen einfach ein Sternchen hinschreiben.

Beachten Sie: Wenn man SQL in eigene Programme einbaut, ist das Sternchen keine gute Idee. Zum einen können Änderungen am Tabellenlayout unbemerkt Fehlfunktionen auslösen. Zum anderen braucht man längst nicht immer jede Spalte aus dem Ergebnis (gerade bei verknüpften Tabellen) und überflüssige Ergebnisspalten kosten unnötig Speicher und Übertragungszeit. Es ist deshalb üblich, in programmiertem SQL jede Spalte, die man verarbeiten möchte, wie im nachfolgenden Beispiel explizit aufzuführen.

Ergebnis:

MatrNr Name
26120 Fichte
25403 Jonas
27103 Fauler

Abfrage mit Spaltenauswahl

Braucht man nicht alle Spalten, listet man die gewünschten Spalten einzeln, durch Komma getrennt, auf. Diesen Vorgang nennt man Projektion.

SELECT VorlNr, Titel
FROM Vorlesung;

liest die Spalten VorlNr und Titel aller Zeilen der Tabelle Vorlesung.

Ergebnis:

VorlNr Titel
5001 ET
5022 IT
5045 DB

AS - Abfrage mit Umbenennung

Das Ergebnis eines SELECT ist wieder eine Tabelle. Die Spaltennamen der Tabelle entsprechen zunächst den Spalten der Tabelle, die man im FROM angegeben hat. Das lässt sich durch Hinzufügen von AS ändern.

SELECT MatrNr AS Matrikelnummer, Name
FROM Student;

Der Befehl liest die Spalten MatrNr und Name der Student-Tabelle. In der Ergebnistabelle heißt die MatrNr-Spalte aber Matrikelnummer.

Ergebnis:

Matrikelnummer Name
26120 Fichte
25403 Jonas
27103 Fauler

WHERE - Abfrage mit Filter

Man kann ein Abfrageergebnis auch auf bestimmte Zeilen eingrenzen. Dazu dient die WHERE-Klausel. Sie listet die Bedingungen auf, die die gewünschten Zeilen erfüllen sollen. Sie folgt auf die FROM-Klausel. Der Fachbegriff für diese Eingrenzung ist Selektion.

Die Bedingungen, die hinter WHERE angeführt werden können, bestehen wie in Programmiersprachen aus Operanden und Operatoren. Operanden können Spaltennamen sein oder konstante Werte. Einer der Operatoren ist =, der zu einem logischen WAHR ausgewertet wird, wenn seine Operanden gleich sind:

SELECT VorlNr, Titel
FROM Vorlesung
WHERE Titel = 'ET';

listet VorlNr und Titel aller derjenigen Zeilen der Tabelle Vorlesung auf, deren Titel 'ET' ist.

Es hängt von den Einstellungen der Datenbank ab, ob der = Operator Groß- und Kleinschreibung beim Vergleich beachtet. Es ist aber auf jeden Fall so, dass Leerstellen am Ende einer Zeichenkette ignoriert werden.

Die solchermaßen strukturierte, häufig verwendete Anweisung wird nach den Anfangsbuchstaben auch als „SFW-Block“ bezeichnet.

Ergebnis:

VorlNr Titel
5001 ET
Beachten Sie: SQL-Queries werden gerne einzeilig geschrieben. Damit aber die SQL-Fehlermeldung noch hilfreicher wird, kann man (zumindest beim Debugging) mehrere Zeilen benutzen. Dann steht am Ende nicht immer "at line 1", sondern die betreffende Zeile.[1]
// statt einer Zeile...
$query = 'SELECT foo, bar FROM table WHERE answer=42';

// mehrere nutzen und Heredoc-Syntax verwenden
$query = <<<SQL
   SELECT
      foo,
      bar
   FROM 
      table 
   WHERE 
      answer=42
   SQL;

Warum haben wir den HEREDOC-String mit SQL begrenzt und nicht, wie man es zumeist findet, mit END? Auf diese Weise wird deutlich gemacht, dass es sich bei diesem String um SQL handelt und nicht im irgendeinen String. Und vor allem: Editoren wie Visual Studio Code greifen diesen Hinweis auf und schalten ihr Code-Highlighting von PHP auf SQL um! Unser Wiki-Highlighter beherrscht diesen Trick leider nicht.

WHERE und AS - wer gewinnt?

Schauen Sie sich diese Abfrage an:

SELECT Name AS Teilnehmername
FROM Student
WHERE Teilnehmername LIKE 'F%';

Gelingt diese Query? Nein. Oder vielleicht doch, je nachdem, wie hellsichtig Ihre SQL Umgebung ist. Der Normalfall ist jedoch, dass die Query zurückgewiesen wird, weil die Spalte </code>Teilnehmername</code> unbekannt ist. Aliasnamen im SELECT-Teil der Abfrage werden erst zugewiesen, wenn die Spaltenauswahl stattfindet, und das ist bei der Verarbeitung von WHERE noch nicht geschehen.

LIKE - Abfrage mit Filter nach Inhalt

Ein anderer Operator ist LIKE. Er führt einen Mustervergleich durch, ähnlich der Mustersuche nach Dateinamen mit * und ?.

SELECT Name
FROM Student
WHERE Name LIKE 'F%';

listet die Namen aller Studenten auf, deren Name mit F beginnt (im Beispiel: Fichte und Fauler).

LIKE kann mit verschiedenen Platzhaltern verwendet werden: _ steht für ein einzelnes beliebiges Zeichen, % steht für eine beliebige Zeichenfolge. Manche Datenbanksysteme bieten weitere solche Wildcard-Zeichen an, etwa für Zeichenmengen.

Ergebnis:

Name
Fichte
Fauler

Programmiertechnik/Kontextwechsel#Besonderheit:_der_LIKE-Operator

Beachten Sie: Es gibt Datenbanken, deren SQL Dialekt andere Platzhalterzeichen verwendet, beispielsweise Microsoft Access.

ORDER BY - Abfrage mit Filter und Sortierung

Wenn die Ergebnisse einer Abfrage in einer bestimmten Reihenfolge erwartet werden, kann man sie sortieren lassen. Dafür fügt man am Ende des SELECT Befehl die ORDER BY Klausel an. Sie benennt die Spalten, nach deren Inhalt zu sortieren ist. Ohne weitere Angaben erfolgt die Sortierung aufsteigend, durch Hinzufügen des Schlüsselwortes DESC wird diese Spalte absteigend sortiert.

SELECT Vorname, Name, StrasseNr, Plz, Ort
FROM Student
WHERE Plz = '20095'
ORDER BY Name, Vorname DESC

listet Vorname, Name, StrasseNr, Plz und Ort aller Studenten aus dem angegebenen Postleitzahlbereich sortiert nach Name auf. Studenten mit gleichem Nachnamen werden absteigend nach Vorname sortiert.

Abfrage mit verknüpften Tabellen

Hinweis:
Dieser Abschnitt reißt das Thema nur an. Eine ausführlichere Darstellung befindet sich im Artikel Einführung in JOINs.

Oft müssen für Datenbankabfragen die Inhalte mehrerer Tabellen miteinander kombiniert werden. Der Fachbegriff hierfür ist JOIN. Dabei geht man so vor, dass man mit der zentralen Tabelle der Abfrage beginnt und die nötigen weiteren Tabellen anknüpft:

SELECT Vorlesung.VorlNr, Vorlesung.Titel, Professor.PersNr, Professor.Name
FROM Professor
     JOIN Vorlesung ON Professor.PersNr = Vorlesung.PersNr;

Ein JOIN wird standardmäßig so gebildet, dass nur die Zeilen aus Professor- und Vorlesung-Tabelle Verwendung finden sollen, für die die Join-Bedingung erfüllbar ist. Ein Professor, der keine Vorlesung hält, oder eine Vorlesung mit einer in Professor unbekannten PersId würden also nicht aufgelistet werden. Es gibt alternative Join-Verfahren, die im Artikel über Joins beschrieben werden.

Die theoretische Idee einer solchen Verknüpfung ist, dass das DBMS alle möglichen Kombinationen von Professoren und Vorlesungen bildet, das so genanntes kartesische Produkt. Bei 10 Professoren und 20 Vorlesungen wären das 200 mögliche Kombinationen. Wir wollen aber je Professor nur die Vorlesungen haben, die er auch hält, und schränken darum diese Kombinationen in der ON-Bedingung auf diejenigen ein, wo die PersNr des Professors mit der in der Vorlesung gespeicherten PersNr übereinstimmt.

In der Praxis wäre dieses Vorgehen unglaublich aufwändig und kein Datenbankserver geht gemäß der reinen Theorie vor. Das wichtigste Element eines Datenbankservers ist der Query Optimizer, der für solche Querys den bestmöglichen Ausführungsplan findet.

Die JOIN-Syntax ist heute in allen Datenbanken verfügbar, mit Ausnahme einiger Sonderformen in Datenbanken, die auf wenig Speicherverbrauch optimiert sind (wie beispielsweise SQLite).

Beachten Sie: Die ON-Bedingung ist zwar schon seit über 30 Jahren im Standard (SQL-92), es hat aber gedauert, bis SQL-92 überall umgesetzt war. Möglicherweise finden Sie noch SQL-Beispiele, die Joins auf die alte Art machen: Die benötigten Tabellen durch Komma getrennt auflisten und die Verknüpfungsbedingung im WHERE-Teil formulieren:
SELECT Vorlesung.VorlNr, Vorlesung.Titel, Professor.PersNr, Professor.Name
FROM Professor, Vorlesung 
WHERE Professor.PersNr = Vorlesung.PersNr;

Die Join-Bedingung (egal ob in ON oder WHERE) kann auf beliebige Weise gestaltet werden. Sie können beliebige Vergleichsoperatoren verwenden, auch SQL-Funktionen sind zulässig. Sie können Spalten der beteiligten Tabellen vergleichen, Sie können aber auch Spaltenwerte mit Konstanten vergleichen.

In ON-Bedingungen ist allerdings zu beachten, dass man darin nur auf diejenigen Tabellen zugreifen kann, die bis zu diesem Punkt eingeführt wurden. Wenn Sie drei Tabellen mit JOIN verknüpfen, können Sie in der ON-Bedingung des zweiten JOIN nicht auf die Tabelle im dritten JOIN zugreifen.

Was das Beispiel auch zeigt, ist der Umgang mit mehrdeutigen Namen. Die Professor- und Vorlesung-Tabelle enthalten beide eine Spalte mit dem Namen PersNr. Würde man ON PersNr = PersNr schreiben, wüsste das DBMS nicht, was gemeint ist. Um das aufzulösen, kann man eine Spalte den Namen der Tabelle voranstellen, in der sie zu finden ist.

Aliasnamen für Tabellen

Wenn die Herkunft eines Spaltennamens nicht eindeutig ist, kann es mühsam werden, immer den vollständigen Tabellennamen hinzuzufügen. Um das zu vereinfachen, erlaubt SQL die Vergabe eines Aliasnamens auch für Tabellen. SQL schaut normalerweise nicht nach vorn, aber Tabellenaliase können auch im SELECT schon benutzt werden (der Grund dafür steht in der Zusammenfassung am Ende dieses Kapitels):

SELECT v.VorlNr, v.Titel, p.PersNr, p.Name
FROM Professor AS p
     JOIN Vorlesung v ON p.PersNr = v.PersNr;

Das Schlüsselwort AS ist optional. Bei der Vorlesung Tabelle haben wir es einfach weggelassen.

COUNT & Co - Aggregat-Funktionen

Eine häufige Aufgabe beim Abfragen umfangreicher Datenbestände ist ihre Verdichtung. Man möchte zählen, summieren, Durchschnitte bilden, oder Minima und Maxima finden. SQL unterstützt standardmäßig genau diese fünf Operationen durch die sogenannten Aggregatfunktionen COUNT, SUM, AVG, MIN und MAX. Werden diese Funktionen in einer einfachen SFW-Abfrage eingesetzt, ist das Ergebnis genau eine einzige Zeile. Es ist sinnvoll, die Aggregatfunktionen mit AS zu kombinieren, um den Namen der Ergebnisspalte festzulegen.

SELECT COUNT(*) AS Anzahl, MAX(Name) AS MaxName FROM Professor

Ergebnis:

Anzahl MaxName
3 Wirth

Das Beispiel soll alle Sätze zählen, darum wird der COUNT-Funktion ein Stern als Argument übergeben. Durch Angabe eines Spaltennamens würden alle Zeilen gezählt, in denen diese Spalte nicht den speziellen Wert NULL enthält.

GROUP BY - Bilden von Teilmengen

Nicht immer will man alle Sätze aggregieren. Man kann auch Teilmengen bilden. Betrachten wir ein etwas umfangreicheres Beispiel:

Student
MatrNr Name PLZ StudGang
26120 Schmitz 50933 E-Technik
21391 Meyer 50933 Physik
25403 Jonas 10365 Physik
14983 Eifrig 10365 Mathematik
27103 Fauler 80769 E-Technik

Mit der Abfrage

SELECT StudGang AS Studiengang, COUNT(*) AS Anzahl
FROM Student
GROUP BY StudGang
ORDER BY StudGang

werden die ermittelten Zeilen nach Studiengang gruppiert und die Anzahl gebildet

Ergebnis:

Studiengang Anzahl
E-Technik 2
Mathematik 1
Physik 2

Ohne Angabe einer ORDER BY Klausel ist die Reihenfolge der Sätze nicht definiert. Das Ergebnis kann aufsteigend nach den Gruppierspalten sortiert sein, aber das ist ohne ORDER BY nicht gewährleistet.

Beachten Sie: Werden Aggregatfunktionen verwendet, dann dürfen in der SELECT Klausel nur solche Spalten ohne Aggregatfunktion stehen, die unter GROUP BY angegeben sind. Viele Datenbanksysteme geben einen Fehler aus, wenn man sich nicht daran hält. MySQL ist eine Ausnahme, es erlaubt auch die Angabe von Spalten ohne Aggregatfunktion, die nicht unter GROUP BY aufgeführt sind. Ausgegeben wird dann aber irgendein Wert dieser Spalte der für diese Gruppe ausgewählten Zeilen.

DISTINCT - Abfrage mit eindeutigen Werten

Eine Sonderform der Gruppierung ist das Reduzieren einer Ergebnismenge auf eindeutige Werte. Wenn man aus der im vorigen Abschnitt gezeigten, erweiterten Student-Tabelle eine Liste der belegten Studiengänge ermitteln möchte, dann ist

SELECT StudGang FROM Student

falsch – man möchte ja E-Technik und Physik nur einmal ausgeben. Man kann es mit GROUP BY lösen:

SELECT StudGang
FROM Student
GROUP BY StudGang

Aber weil das eine recht häufige Aufgabe ist, gibt es dafür das Schlüsselwort DISTINCT in der SELECT Klausel:

SELECT DISTINCT StudGang FROM Student

DISTINCT bezieht sich nicht auf eine Spalte, sondern auf die komplette Ergebniszeile. Listet man mehrere Spalten auf, werden nur die Zeilen zusammengefasst, bei denen alle Spaltenwerte gleich sind.

DISTINCT lässt sich auch in der Aggregatfunktion COUNT einsetzen:

SELECT COUNT(StudGang), COUNT(DISTINCT StudGang) FROM Student

ermittelt zwei Werte: Die Anzahl der Studenten, für die StudGang nicht NULL ist (ohne DISTINCT) und die Anzahl von unterschiedlicher Studiengängen, die von den Studenten belegt wurden (mit DISTINCT).

HAVING - Filtern von aggregierten Werten

Wenn man die GROUP BY Klausel einsetzt, kann die Aufgabe entstehen, dass man nur die Gruppen sehen möchte, für die ein aggregiertes Ergebnis bestimmte Bedingungen erfüllt. Beispielsweise möchte man alle Studiengänge finden, für die die Menge der eingeschriebenen Studenten eine Mindestmenge unterschreitet. Eine Abfrage, die die Anzahl der Studenten pro Studiengang findet, wurde bereits weiter oben gezeigt. Eine Filterung des COUNT-Ergebnisses mittels WHERE ist aber nicht möglich, weil die WHERE-Filterung vor der Gruppierung stattfindet. Dafür gibt es eine eigene Klausel: HAVING.

SELECT StudGang AS Studiengang, COUNT(*) AS Anzahl
FROM Student
GROUP BY StudGang
HAVING COUNT(*) < 2
ORDER BY StudGang

In der HAVING Klausel muss die zu filternde Spalte genauso spezifiziert werden wie in der SELECT Klausel. Der mit AS angegebene Aliasname für diese Spalte kann im Allgemeinen nicht verwendet werden. MySQL ist hier wieder die Ausnahme, dort wäre HAVING Anzahl < 2 zulässig.

Ergebnis:

Studiengang Anzahl
Mathematik 1

Für Mathe ist wohl etwas mehr Werbung nötig.

Mengenoperatoren: UNION, EXCEPT und INTERSECT

Mengenoperatoren können dazu genutzt werden, die Ergebnismengen mehrerer SELECT-Abfragen zusammenzufügen. Voraussetzung ist, dass diese SELECTs gleich viele Attribute auslesen und die Datentypen der Attribute übereinstimmen.

Mengenoperator UNION
SELECT userid, username, lastlogin, 'A-Forum' as Quelle
FROM   forum1.users 
WHERE  userlevel=9
UNION
SELECT userid, username, lastlogin, , 'B-Forum'
FROM   forum2.users
WHERE  userlevel=9
ORDER BY lastlogin

Das Beispiel würde aus den user-Tabellen zweier DB-Schemas alle User mit Level 9 lesen und als eine Tabelle ausgeben. Um im Ergebnis die Herkunft des Users sehen zu können, wird in den Selects eine vierte Spalte erzeugt, in der eine Konstante eingetragen ist. Der ORDER BY wirkt auf die Gesamtergebnismenge.

  • UNION vereinigt die Ergebnismengen der beteiligten SELECT-Abfragen zu einer einzigen Menge. Je nach verwendetem Datenbanksystem gibt es noch die erweiterten Formen UNION DISTINCT und UNION ALL, um anzugeben, ob doppelt vorkommende Ergebnistupel entfernt werden (DISTINCT) oder erhalten bleiben (ALL) sollen. Der Normalfall ist, dass UNION wie UNION DISINCT wirkt und ein UNION ALL explizit angegeben werden muss. Es gibt aber auch Datenbanksysteme, die UNION wie UNION ALL interpretieren und die ALL Option gar nicht erkennen. Die explizite Angabe von DISTINCT wird ebenfalls nicht von allen Datenbanksystemen erkannt. Bitte schauen Sie im Handbuch Ihres Datenbanksystems nach, wie die konkrete Handhabung aussieht.
  • EXCEPT nimmt die Tupel, die in der vor EXCEPT stehenden Ergebnismenge enthalten sind und entfernt daraus diejenigen Tupel, die in der Ergebnismenge hinter EXCEPT stehen. Mehrfach vorkommende Ergebnistupel werden entfernt. Einige SQL Dialekte verwenden statt EXCEPT das Schlüsselwort MINUS.
  • INTERSECT liefert die Schnittmenge zweier Ergebnismengen. Mehrfach vorkommende Ergebnistupel werden entfernt.

Das häufig verwendete Datenbanksystem MySQL kennt UNION und auch die erweiterten Formen UNION DISTINCT und UNION ALL. Ein einfacher UNION wird wie UNION DISTINCT behandelt. Die Mengenoperatoren EXCEPT und INTERSECT kennt es dagegen nicht, diese Operatoren lassen sich aber mit Hilfe eines JOIN oder Subselect nachbauen.

Zusammenfassung

Zusammengefasst sind die wichtigsten Elemente einer SQL-SELECT-Abfrage wie folgt anzugeben:

SELECT [DISTINCT] Auswahlliste [AS Spaltenalias]
FROM Quelle [ [AS] Tabellenalias]
[WHERE Where-Klausel]
[GROUP BY (Group-by-Attribut)+]
[HAVING Having-Klausel]
[ORDER BY (Sortierungsattribut [ASC|DESC])+];

Erläuterung:

  • DISTINCT gibt an, dass aus der Ergebnisrelation gleiche Ergebnistupel entfernt werden sollen. Es wird also jeder Datensatz nur einmal ausgegeben, auch wenn er mehrfach in der Tabelle vorkommt. Sonst liefert SQL eine Multimenge zurück.
  • Auswahlliste bestimmt, welche Spalten der Quelle auszugeben sind ( * für alle) und ob Aggregatfunktionen anzuwenden sind. Wie bei allen anderen Aufzählungen werden die einzelnen Elemente mit Komma voneinander getrennt.
  • Quelle gibt an, wo die Daten herkommen. Es können Relationen und Sichten angegeben werden und miteinander als kartesisches Produkt oder als Verbund (JOIN, ab SQL-92) verknüpft werden. Mit der zusätzlichen Angabe eines Namens können Tupelvariablen besetzt werden, also Relationen für die Abfrage umbenannt werden).
  • Where-Klausel bestimmt Bedingungen, auch Filter genannt, unter denen die Daten ausgegeben werden sollen. In SQL ist hier auch die Angabe von Unterabfragen möglich, sodass SQL streng relational vollständig wird.
  • Group-by-Attribut legt fest, ob unterschiedliche Werte als einzelne Zeilen ausgegeben werden sollen (GROUP BY = Gruppierung) oder aber die Feldwerte der Zeilen durch Aggregationen wie Addition (SUM), Durchschnitt (AVG), Minimum (MIN), Maximum (MAX) zu einem Ergebniswert zusammengefasst werden, der sich auf die Gruppierung bezieht.
  • Having-Klausel ist wie die Where-Klausel, nur dass sich die angegebene Bedingung auf das Ergebnis einer Aggregationsfunktion bezieht, zum Beispiel HAVING SUM (Betrag) > 0.
  • Sortierungsattribut: nach ORDER BY werden Attribute angegeben, nach denen sortiert werden soll. Die Standardvoreinstellung ist ASC, das bedeutet aufsteigende Sortierung, DESC ist absteigende Sortierung.
Beachten Sie: Die Reihenfolge, in der die Klauseln eines SQL Statements notiert werden, ist nicht ganz die Reihenfolge, in der der SQL Server sie abarbeitet. Der reinen Lehre nach geschieht dies:
  • die in FROM und JOIN angegebenen Tabellen werden gelesen und miteinander zum kartesischen Produkt ihrer Zeilen verknüpft, unter Beachtung der mit ON formulierten Bedingungen (siehe den Abschnitt zu verknüpften Tabellen)
  • die Zeilen des kartesischen Produkts werden durch die WHERE-Bedingungen gefiltert. Gute SQL Server kombinieren Schritt 1 und 2, um nicht sinnlos ein riesiges kartesisches Produkt aufzubauen.
  • die Ergebniszeilen können nun an Hand der GROUP BY Angaben zusammengefasst werden. Dazu werden sie nach den Gruppierbegriffen sortiert. Das Ergebnis der Zusammenfassung besteht aus den Gruppierbegriffen und den Ergebnissen der Aggregatfunktionen, die in der Select-Liste verwendet wurden.
  • das Ergebnis der Zusammenfassung kann erneut an Hand der HAVING Angaben gefiltert werden
  • jetzt erst findet die Auswahl der im SELECT angegebenen Spalten, die Zuweisung der mit AS vergebenen Aliasnamen und die DISTINCT-Filterung statt.
    • Spalten, die beim Gruppieren entfallen sind, stehen nicht mehr zur Verfügung.
    • Weil Aliasnamen erst jetzt zugewiesen werden, sind sie in den WHERE, GROUP BY und HAVING Klauseln nicht verfügbar
    • MySQL/MariaDB sind hier nicht standardkonform.
      Zum ersten erlauben sie die Nennung einer nicht gruppierten Spalte. Der Wert, den man erhält, stammt allerdings aus einer zufälligen Zeile der jeweiligen Gruppe!
      Zum zweiten erlauben sie in GROUP BY und HAVING die Verwendung von Aliasnamen aus der SELECT-Klausel
  • Zum Abschluss kann das Ergebnis limitiert werden. Die Syntax dazu ist unterschiedlich, MySQL verwendet LIMIT am Ende der Query, Microsoft SQL Server eine TOP n Option im SELECT.

Datensätze hinzufügen und ändern

INSERT INTO

Mit INSERT können Sie neue Datensätze hinzufügen:

INSERT INTO <Tabellenname>(<Spaltenname> [, weitere Spaltennamen])
VALUES (<Wert für die erste Spalte> [, weitere Werte])

Hinter VALUES werden alle einzufügenden Werte der Reihe nach aufgelistet. Es wird genau eine neue Zeile erzeugt.

INSERT INTO Professor (PersNr, Name) 
VALUES (21, 'Hastig')

Einfügen mehrerer Zeilen:

INSERT INTO <Tabellenname>(<Spaltenname> [, weitere Spaltennamen])

	SELECT <Spalte-1> [, weitere Ausgaben]
	[FROM ...]
	[WHERE ...]
	[GROUP BY ...]
	[HAVING ...]

UPDATE

Mit UPDATE können Sie Werte innerhalb eines vorhandenen Datensatzes aktualisieren.

UPDATE tabellen_name 
SET tabellen_spalte = wert1 
WHERE tabellen_spalte = wert2
Beachten Sie, dass ohne Angabe eines WHERE-Blocks alle Datensätze geändert werden.

DELETE

Mit DELETE können Sie Werte innerhalb eines vorhandenen Datensatzes löschen.

DELETE FROM tabellen_name 
WHERE spalten_name = wert
Beachten Sie, dass ohne Angabe eines WHERE-Blocks alle Datensätze gelöscht werden.

Tabellen erzeugen

In den vorhergehenden Kapiteln wurden bestehende Datenbanken ausgelesen und erweitert. Die Datenbanktabellen können mit Programmen wie phpMyAdmin oder auch mit SQL selbst angelegt werden.

Achtung!

Das Löschen, aber auch das Anlegen von Tabellen kann (durch Überschreiben bestehender Tabellen) zu Datenverlust führen.

Legen Sie regelmäßig Backups an!

CREATE

CREATE TABLE tabellennamen
(
   Spaltenname1 datentyp1 [feldeinschränkung]
   Spaltenname2 datentyp2 [feldeinschränkung]
   [...]
);

http://www.sql-lernen.de/create-table.php


Urheberrechtlicher Hinweis

Dieser Artikel sowie die darin enthaltenen Abbildungen wurden als Bearbeitung eines Artikels der Wikipedia erstellt, der unter den Lizenzbedingungen der Lizenz "Creative Commons Attribution-ShareAlike 3.0 Unported" steht und wird deshalb unter Namensnennung zu den gleichen Bedingungen weitergegeben. Die Autoren des ursprünglichen Artikels gehen aus der Versionsgeschichte bei Wikipedia hervor.



Quellen

  1. SELF-Forum: SQL Abfrage: wo liegt mein Fehler Henman von 19.11.2015


Siehe auch

→ alle Seiten der Kategorie:DBMS und SQL