SQL-Grundlagen

SQL ist die Sprache, mit der du eine Datenbank nach Daten fragst, Daten einfügst und änderst. Dieser Leitfaden beginnt mit der Reihenfolge, in der eine SELECT-Anweisung verarbeitet wird, und führt dich dann Schritt für Schritt durch Funktionen und GROUP BY, Joins, Unterabfragen, Fensterfunktionen und hierarchische Abfragen bis zu den Anweisungen, mit denen du Daten änderst und Änderungen festschreibst. Die Beispiele verwenden durchgehend eine Mitarbeiter- und eine Abteilungstabelle, und in jedem Kapitel gibt es eine Grafik, die du selbst ausprobieren kannst. Die Erklärungen gehen von Oracle aus; wo sich SQL Server anders verhält, steht das jeweils dabei. Wie du Tabellen aufteilst und entwirfst, erklärt der Leitfaden Datenmodellierung.

01

Relationale Datenbanken und SELECT-Grundlagen

Die Begriffe relationaler Datenbanken

Eine relationale Datenbank speichert Daten in Tabellen (aus Zeilen und Spalten) und verknüpft Tabellen über Schlüsselwerte. In der Theorie heißen dieselben Dinge anders, deshalb lohnt es sich, die Paare zu kennen.

Theorie (Relationenmodell)In der TabelleBedeutung
RelationTabelleEine Menge von Zeilen mit derselben Struktur
TupelZeileEine einzelne Instanz
AttributSpalteEine einzelne Eigenschaft
Grad (Degree)Anzahl der SpaltenAnzahl der Attribute
Kardinalität (Cardinality)Anzahl der ZeilenAnzahl der Tupel
DomäneWertebereich einer SpalteDie Menge der Werte, die ein Attribut annehmen kann

Relationen haben feste Eigenschaften: Es kann keine zwei identischen Tupel geben, weder Tupel noch Attribute haben eine Reihenfolge, und jeder Wert ist atomar, lässt sich also nicht weiter zerlegen.

Auch bei den Schlüsseln gibt es verschiedene Arten.

SchlüsselBedingung
SuperschlüsselNur Eindeutigkeit – jede Spaltenkombination, mit der sich Zeilen unterscheiden lassen
SchlüsselkandidatEindeutigkeit + Minimalität – ein möglicher Primärschlüssel
Primärschlüssel (PK)Der Schlüsselkandidat, der als Hauptschlüssel gewählt wird. Kein NULL, keine Duplikate
AlternativschlüsselDie übrigen Schlüsselkandidaten, die nicht Primärschlüssel geworden sind
Fremdschlüssel (FK)Eine Spalte, die auf den Primärschlüssel einer anderen Tabelle verweist

Die Regeln, die dafür sorgen, dass die Daten immer korrekt bleiben, heißen Integritätsbedingungen. Die wichtigsten sind die Entitätsintegrität (ein Primärschlüssel darf weder NULL noch doppelt sein), die referenzielle Integrität (ein Fremdschlüsselwert muss in der referenzierten Tabelle vorkommen oder NULL sein) und die Domänenintegrität (ein Spaltenwert muss in seiner festgelegten Domäne liegen).

Die theoretischen Operationen relationaler Datenbanken heißen Relationenalgebra. So passen die Teile von SQL zu diesen Operationen:

ArtOperationSymbolIn SQL
Reine relationale OperatorenSELECT (Selektion)σWHERE – wählt die Zeilen aus, die die Bedingung erfüllen
PROJECT (Projektion)πSELECT-Liste – wählt die gewünschten Spalten aus
JOIN (Verbund)⋈JOIN – verbindet zwei Relationen über gemeinsame Werte
DIVISION÷Behält nur Zeilen, die alle Werte des Divisors haben (keine direkt passende Syntax)
Allgemeine MengenoperatorenVereinigung / Schnittmenge / Differenz∪ / ∩ / −UNION / INTERSECT / MINUS (EXCEPT)
Kartesisches Produkt×CROSS JOIN

Die vier Arten von SQL-Anweisungen

ArtBefehleWas sie tun
DML (Bearbeitung)SELECT, INSERT, UPDATE, DELETE, MERGEDaten abfragen, einfügen, ändern und löschen. SELECT allein wird manchmal auch DQL genannt
DDL (Definition)CREATE, ALTER, DROP, RENAME, TRUNCATEStrukturen wie Tabellen anlegen, ändern und entfernen
DCL (Steuerung)GRANT, REVOKEBerechtigungen vergeben und entziehen
TCL (Transaktionssteuerung)COMMIT, ROLLBACK, SAVEPOINTÄnderungen festschreiben oder zurücksetzen

SELECT und WHERE

Das Grundgerüst von SELECT sieht so aus:

SELECT [DISTINCT] spalte [AS alias], ...
FROM   tabelle
WHERE  bedingung
ORDER BY spalte [ASC | DESC];
  • DISTINCT entfernt doppelte Zeilen aus dem Ergebnis (als doppelt gilt eine Zeile nur, wenn die ganze SELECT-Liste gleich ist)
  • Einen Alias vergibst du mit AS; enthält er Leerzeichen oder Sonderzeichen, setzt du ihn in doppelte Anführungszeichen
  • Zum Verketten von Zeichenketten nutzt Oracle || und SQL Server + (die Funktion CONCAT gibt es in beiden)

Diese Operatoren verwendest du in WHERE:

OperatorBedeutungAchtung
=, <>, !=, ^=, >, <, >=, <=Vergleich<>, != und ^= bedeuten alle „ungleich“
BETWEEN a AND bmindestens a und höchstens bBeide Grenzwerte sind eingeschlossen. Der kleinere Wert kommt zuerst
IN (a, b, c)gleich einem Wert aus der ListeSteht in einer NOT-IN-Liste ein NULL, kommt gar kein Ergebnis zurück
LIKE 'A%'Muster% steht für beliebig viele Zeichen (auch keins), _ für genau ein Zeichen. Um % selbst zu suchen, brauchst du ESCAPE
IS NULL / IS NOT NULList NULL?= NULL ist immer „unbekannt“ und liefert keine einzige Zeile

Verknüpfst du mehrere Bedingungen, gibt es eine Rangfolge. Laut Oracle-Dokumentation gilt: Klammern → Vergleichsoperatoren → NOT → AND → OR. AND kommt vor OR, deshalb wird A OR B AND C als A OR (B AND C) ausgewertet. Wenn du dir unsicher bist, setz lieber Klammern.

Warum liefert NOT IN (10, 20, NULL) überhaupt nichts? NOT IN wird zu „ungleich 10 AND ungleich 20 AND ungleich NULL“ aufgelöst – und ein Vergleich mit NULL ist immer „unbekannt“, also kann die Gesamtbedingung nie wahr werden. Wenn im Ergebnis einer Unterabfrage NULL vorkommen kann, nimm NOT EXISTS oder filtere die NULL-Werte vorher heraus.

ORDER BY: Sortieren und wohin NULL kommt

ORDER BY sortiert standardmäßig aufsteigend (ASC), und du kannst nach Spaltenname, Alias oder der Position in der SELECT-Liste (1, 2 …) sortieren. Unterschiede gibt es bei NULL: Oracle behandelt NULL als größten Wert und setzt es bei aufsteigender Sortierung ans Ende, SQL Server als kleinsten Wert und setzt es an den Anfang. In Oracle kannst du die Position mit NULLS FIRST bzw. NULLS LAST selbst festlegen.

In welcher Reihenfolge eine SELECT-Anweisung verarbeitet wird

Eine SELECT-Anweisung wird nicht in der Reihenfolge verarbeitet, in der sie geschrieben ist. Wenn du diese Reihenfolge kennst, beantworten sich Fragen wie „Warum kann ich in WHERE keinen Alias verwenden?“ oder „Warum geht SUM nicht in WHERE?“ auf einen Schlag. Geh in der Grafik unten die Schritte durch.

SELECT DEPT_CODE, SUM(SALARY) AS TOTAL
▶FROM EMP
WHERE SALARY >= 260
GROUP BY DEPT_CODE
HAVING SUM(SALARY) >= 280
ORDER BY TOTAL DESC;

EMP

EMP_NONAMEDEPT_CODESALARY
101AnnaD10300
102BenD10250
103ClaraD20400
104DavidD20350
105EmilNULL280
106FriedaD30260

Schritt 1 – FROM

Verarbeitungsreihenfolge
FROM

Geh die Schritte durch. Die Reihenfolge, in der die Abfrage geschrieben ist (SELECT oben), ist nicht die Reihenfolge, in der sie verarbeitet wird.

FROM kommt zuerst. Es holt alle 6 Zeilen der Tabelle EMP. SELECT steht zwar ganz oben, wird aber tatsächlich erst fast am Ende verarbeitet.

Zusammengefasst: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. Der Alias entsteht erst in SELECT, deshalb kannst du ihn nur im danach folgenden ORDER BY verwenden.

Steht in der Frage … → wähle das

  • “Anzahl der Spalten / Zeilen einer Relation”Grad / Kardinalität
  • “Erfüllt Eindeutigkeit und Minimalität”Schlüsselkandidat
  • “Fremdschlüssel ist ein Wert der referenzierten Tabelle oder NULL”Referenzielle Integrität
  • “Relationale Operation, die nur die gewünschten Spalten auswählt”PROJECT (π)
  • “GRANT und REVOKE”DCL
  • “BETWEEN 100 AND 200”100 und 200 eingeschlossen
  • “NULL in einer NOT-IN-Liste”0 Zeilen im Ergebnis
  • “Position von NULL bei aufsteigender Sortierung in Oracle”Am Ende (in SQL Server am Anfang)
  • “Warum WHERE keinen SELECT-Alias verwenden kann”WHERE wird vor SELECT verarbeitet

02

Funktionen und GROUP BY / HAVING

Mit SELECT hast du Spalten geholt. Jetzt bearbeitest du Werte (Funktionen) und fasst sie zusammen (GROUP BY).

Einzeilenfunktionen: ein Wert pro Zeile

Es gibt zwei Arten von Funktionen: Einzeilenfunktionen, die für jede Zeile genau ein Ergebnis liefern, und Mehrzeilenfunktionen (Aggregatfunktionen), die mehrere Zeilen zu einem einzigen Ergebnis zusammenfassen. Einzeilenfunktionen kannst du überall verwenden – in SELECT, WHERE und ORDER BY –, und du kannst Funktionen auch ineinander verschachteln.

ArtOracleSQL ServerBeispiel und Ergebnis
ZeichenLOWER, UPPERLOWER, UPPERUPPER('sql') → 'SQL'
SUBSTRSUBSTRINGSUBSTR('DATABASE', 3, 4) → 'TABA'
LENGTHLENLENGTH('SQL') → 3
LTRIM, RTRIM, TRIMLTRIM, RTRIM, TRIMTRIM(' A ') → 'A'
CONCAT, ||CONCAT, +'A' || 'B' → 'AB'
ZahlenROUND, TRUNCROUNDROUND(38.567, 1) → 38.6 / TRUNC(38.567, 1) → 38.5
CEIL, FLOORCEILING, FLOORCEIL(3.1) → 4 / FLOOR(-3.1) → -4
MOD%MOD(7, 3) → 1
DatumSYSDATEGETDATE()Aktuelles Datum und Uhrzeit
EXTRACTDATEPARTEXTRACT(YEAR FROM HIRE_DATE)

Addierst du in Oracle eine Zahl zu einem Datum, wird in Tagen gerechnet: HIRE_DATE + 1 ist der nächste Tag, HIRE_DATE + 1/24 eine Stunde später. Und noch etwas: Oracle behandelt eine leere Zeichenkette (‘’) als NULL, während SQL Server zwischen leerer Zeichenkette und NULL unterscheidet.

Typkonvertierung und CASE

Datentypen lassen sich auf zwei Arten umwandeln: per expliziter Konvertierung, bei der du selbst eine Funktion aufrufst (Oracle: TO_CHAR, TO_NUMBER, TO_DATE; SQL Server: CAST, CONVERT), und per impliziter Konvertierung, bei der die Datenbank das von sich aus erledigt. Implizite Konvertierung ist bequem, kann aber anders umwandeln als erwartet oder verhindern, dass ein Index genutzt wird. Gewöhn dir deshalb an, explizit zu konvertieren.

Soll je nach Bedingung ein anderer Wert herauskommen, verwendest du CASE. Es gibt den einfachen CASE-Ausdruck, der mit einem einzelnen Wert vergleicht, und den gesuchten CASE-Ausdruck mit Bedingungen. Oracle hat außerdem die Funktion DECODE, die dasselbe erledigt.

SELECT NAME,
       CASE WHEN SALARY >= 350 THEN 'High'
            WHEN SALARY >= 280 THEN 'Mid'
            ELSE 'Low' END AS GRADE,       -- ohne ELSE: NULL
       DECODE(DEPT_CODE, 'D10', 'Vertrieb', 'D20', 'Entwicklung', 'Sonstige') AS DEPT_NAME
FROM   EMP;

Funktionen für NULL

FunktionRückgabewertBeispiel
NVL(a, b) / ISNULL(a, b)b, wenn a NULL ist, sonst aNVL(BONUS, 0)
NVL2(a, b, c)b, wenn a nicht NULL ist, c, wenn a NULL ist (Oracle)NVL2(BONUS, 'ja', 'nein')
NULLIF(a, b)NULL, wenn a und b gleich sind, sonst aNULLIF(10, 10) → NULL
COALESCE(a, b, c, ...)Der erste Wert, der nicht NULL istCOALESCE(NULL, NULL, 3) → 3

Aggregatfunktionen und NULL

Aggregatfunktionen wie COUNT, SUM, AVG, MAX und MIN fassen mehrere Zeilen zu einem einzigen Wert zusammen. Merk dir eine Regel: Alle außer COUNT(*) ignorieren NULL. Wechsle in der Grafik unten die Funktion.

EMP

NAMESALARYBONUS
Anna30050
Ben250NULL
Clara400NULL
David35030
Emil280NULL
Frieda26020

COUNT(*) = 6

Berechnung
Verwendete Zeilen
6 / 6

Wechsle die Funktion. Hellgrüne Zeilen fließen in die Rechnung ein, durchgestrichene Zeilen bleiben draußen.

COUNT(*) zählt die Zeilen selbst. Eine Zeile, deren BONUS NULL ist, bleibt trotzdem eine Zeile – das Ergebnis ist also 6.

Steht DISTINCT in einer Aggregatfunktion, wird jeder Wert nur einmal gezählt (COUNT(DISTINCT DEPT_CODE)). Erfüllt keine einzige Zeile die Bedingung, liefert COUNT 0, während SUM, AVG, MAX und MIN NULL zurückgeben.

GROUP BY und HAVING

GROUP BY fasst Zeilen mit gleichen Werten zusammen und aggregiert pro Gruppe. Danach gibt es pro Gruppe nur noch eine Zeile, und daraus ergeben sich ein paar Regeln:

  • Jede Spalte in der SELECT-Liste, die nicht in einer Aggregatfunktion steht, muss auch in GROUP BY stehen
  • In GROUP BY verwendest du keine SELECT-Aliase – laut Verarbeitungsreihenfolge gibt es den Alias da noch nicht (das neueste Oracle 23ai erlaubt es zwar, Prüfungen gehen aber von der klassischen Regel aus)
  • Auch NULL bildet eine eigene Gruppe
  • GROUP BY garantiert keine Sortierung – brauchst du eine Reihenfolge, nimm ORDER BY

Bedingungen für Gruppen schreibst du in HAVING. WHERE filtert Zeilen, bevor gruppiert wird, HAVING filtert Gruppen danach. Deshalb gehören Bedingungen mit Aggregatfunktionen nur in HAVING. Braucht eine Bedingung keine Aggregatfunktion, filterst du besser schon in WHERE – dann müssen weniger Zeilen verarbeitet werden.

SELECT   DEPT_CODE, COUNT(*) AS HEADCOUNT, AVG(SALARY) AS AVG_SAL
FROM     EMP
WHERE    SALARY >= 250          -- zuerst Zeilen filtern
GROUP BY DEPT_CODE
HAVING   COUNT(*) >= 2;         -- nach dem Gruppieren Gruppen filtern

Steht in der Frage … → wähle das

  • “SUBSTR('DATABASE', 3, 4)”'TABA'
  • “Leere Zeichenkette in Oracle”Wird als NULL behandelt
  • “NULL, wenn a und b gleich sind”NULLIF(a, b)
  • “Erster Wert, der nicht NULL ist”COALESCE
  • “Aggregatfunktion, die NULL mitzählt”Nur COUNT(*)
  • “AVG(BONUS) vs. AVG(NVL(BONUS, 0))”Es wird durch unterschiedlich viele Zeilen geteilt
  • “Klausel für Bedingungen mit Aggregatfunktionen”HAVING
  • “Spalte ohne GROUP BY in SELECT”Fehler, wenn sie nicht in einer Aggregatfunktion steht

Nur mit Pro

Bis hierhin ist der Guide kostenlos

Die übrigen 5 Kapitel sind für Pro-Abonnenten freigeschaltet. Jedes bringt weitere 3D-Grafiken und „Steht in der Frage …“-Hinweise, und im letzten Kapitel prüfst du dein Wissen selbst.

  1. 03Joins
  2. 04Unterabfragen, Views und Mengenoperatoren
  3. 05Gruppenfunktionen, Fensterfunktionen und Top N
  4. 06Self-Join, hierarchische Abfragen, PIVOT und reguläre Ausdrücke
  5. 07Verwaltungsanweisungen: DML, TCL, DDL und DCL

Anzeige

PasslyExam

Du kennst jetzt das Konzept. Teste es an Prüfungsfragen

PasslyExam bietet eigene Übungsfragen, Erklärungen und vollständige Probeprüfungen, die sich am offiziellen Prüfungsleitfaden jeder Zertifizierung orientieren. Die Erklärungen zeigen, warum die richtige Antwort stimmt und warum ähnlich klingende Optionen falsch sind. Registriere dich und übe jeden Tag kostenlos.

Prüfungen, in denen dieses Konzept vorkommt

Weitere Guides zu diesem Thema

Guides zu anderen Themen

Alle Konzept-Guides ansehen