SQL-Befehle – Datenbank

Geschätzte Lektüre: 41 Minuten 95 Ansichten

Kompaktes Lernskripte für SQL und Datenbanken

Datenbanken und SQL

Eine Datenbank ist ein organisierter Speicher für strukturierte Daten. Daten werden dort nicht in losen Dateien abgelegt, sondern in Tabellen — ähnlich wie Tabellenkalkulationen, aber mit klaren Regeln und der Möglichkeit, Millionen von Datensätzen effizient zu verwalten.

SQL steht für Structured Query Language (strukturierte Abfragesprache). Mit SQL kommunizieren Sie mit dem Datenbanksystem: Sie stellen Fragen (Abfragen), geben Anweisungen und erhalten strukturierte Antworten.

BegriffErklärung
DatenbankSammlung von Tabellen — der Behälter für alle Daten eines Projekts
TabelleStrukturierter Datenspeicher mit Zeilen und Spalten
Zeile (Row)Ein einzelner Datensatz, z. B. eine Person oder ein Produkt
Spalte (Column)Ein Merkmal aller Datensätze, z. B. Name, Alter, Preis
PrimärschlüsselEindeutige Kennung jedes Datensatzes (meist eine ID-Nummer)
FremdschlüsselVerweis auf den Primärschlüssel einer anderen Tabelle

SQL-Befehle (Konzepte/Statements) : Ein erster Überblick

(Konzepte/Statements)

SQL unterscheidet vier Kategorien von Befehlen. Wir werden heute alle vier kennenlernen:

KategorieBefehle & Bedeutung
DDL (Data Definition Language) — DefinitionCREATE, DROP, ALTER — Tabellen anlegen, löschen, verändern
DML (Data Manipulation Language) — ManipulationINSERT, UPDATE, DELETE — Daten hinzufügen, ändern, löschen
DQL (Data Query Language) — AbfrageSELECT — Daten lesen und abfragen
DCL (Data Control Language) — KontrolleGRANT, REVOKE — Zugriffsrechte (heute nicht Thema)

Datentypen in SQL

Jede Spalte in einer Tabelle hat einen festen Datentyp. Dieser legt fest, welche Art von Daten dort gespeichert werden darf. Die wichtigsten Typen:

DatentypVerwendung & Beispiele
INTGanzzahlen: 1, 42, -7, 1000
DECIMAL(m,n)Dezimalzahlen: DECIMAL(8,2) = bis 8 Stellen, davon 2 nach dem Komma
VARCHAR(n)Text variabler Länge, max. n Zeichen: ‚Müller‘, ‚Berlin‘
TEXTLanger Text ohne feste Längenbegrenzung
DATEDatum im Format YYYY-MM-DD: ‚2024-03-15‘
BOOLEANWahrheitswert: TRUE oder FALSE (intern 1 oder 0)

Hinweis zu VARCHAR
VARCHAR(255) ist eine sehr häufige Wahl für Namen, Titel oder kurze Texte.
Die Zahl in Klammern ist die maximale Zeichenanzahl — nicht die tatsächlich gespeicherte. Ein VARCHAR(255)-Feld, das ‚Anna‘ enthält, belegt nur den Speicherplatz für 4 Zeichen.


phpMyAdmin starten

MAMP muss laufen. Öffnen Sie dann Ihren Browser und rufen Sie folgende Adresse auf:

http://localhost:8888/phpmyadmin

Auf der linken Seite sehen Sie die vorhandenen Datenbanken. Rechts erscheint der Hauptarbeitsbereich. Der Reiter ‚SQL‘ ermöglicht die direkte Eingabe von SQL-Befehlen.


Eine Datenbank anlegen

Wir legen heute eine Beispieldatenbank für ein kleines Online-Buchhandlung-System an. Diese Datenbank trägt den Namen shop und enthält zwei Tabellen: kunden und bestellungen.

-- SQL — Datenbank erstellen
CREATE DATABASE shop
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;
-- utf8mb4_0900_ai_ci ist moderner
USE shop;

CHARACTER SET utf8mb4 und COLLATE utf8mb4_unicode_ci stellen sicher, dass Sonderzeichen (ä, ö, ü, é, …) korrekt gespeichert und sortiert werden. (utf8mb4_0900_ai_ci ist moderner)
USE shop; wählt die soeben erstellte Datenbank aus, so dass alle folgenden Befehle auf sie wirken.


Tabellen anlegen

Eine Tabelle wird mit CREATE TABLE erstellt. Dabei werden alle Spalten mit Name und Datentyp definiert.

-- SQL — Tabelle 'kunden' erstellen
CREATE TABLE kunden (
  id          INT           AUTO_INCREMENT PRIMARY KEY,
  vorname     VARCHAR(100)  NOT NULL,
  nachname    VARCHAR(100)  NOT NULL,
  email       VARCHAR(255)  NOT NULL UNIQUE,
  registriert DATE
);

Erklärung der Schlüsselwörter:
AUTO_INCREMENT: Der Wert dieser Spalte wird automatisch um 1 erhöht — Sie müssen keine ID manuell vergeben.
PRIMARY KEY: Kennzeichnet die Spalte als eindeutigen Identifikator jeder Zeile.
NOT NULL: Das Feld darf nicht leer gelassen werden.
UNIQUE: Kein zwei Datensätze dürfen denselben Wert in dieser Spalte haben.
DATE: Das Datum wird eingesetzt.

-- SQL — Tabelle 'buecher' erstellen
CREATE TABLE buecher (
  id        INT            AUTO_INCREMENT PRIMARY KEY,
  titel     VARCHAR(255)   NOT NULL,
  autor     VARCHAR(150)   NOT NULL,
  preis     DECIMAL(8,2)   NOT NULL,
  lagernd   BOOLEAN        DEFAULT TRUE
);
-- SQL — Tabelle 'bestellungen' erstellen
CREATE TABLE bestellungen (
  id          INT    AUTO_INCREMENT PRIMARY KEY,
  kunden_id   INT    NOT NULL,
  buch_id     INT    NOT NULL,
  bestelldatum DATE,
  FOREIGN KEY (kunden_id) REFERENCES kunden(id),
  FOREIGN KEY (buch_id)   REFERENCES buecher(id)
);

FOREIGN KEY verbindet diese Tabelle mit den Tabellen kunden und buecher. Das verhindert, dass eine Bestellung auf eine nicht existierende Kunden-ID oder Buch-ID verweisen kann.

Gut zu wissen: Tabellenstruktur ansehen
Um die Struktur einer bestehenden Tabelle zu sehen, nutzen Sie:
DESCRIBE kunden; Um alle Tabellen in der aktuellen Datenbank aufzulisten: SHOW TABLES;


Tabelle löschen und verändern

-- SQL — Tabelle löschen und Spalte hinzufügen
----------------------------------------------------------

-- Tabelle löschen (Vorsicht: alle Daten gehen verloren)
DROP TABLE IF EXISTS bestellungen;
-- DROP 👉 bedeutet: löschen
-- IF EXISTS 👉 bedeutet: nur wenn sie existiert
-- TABLE 👉 Tabelle
-- Übersetzt: 
-- Lösche die Tabelle bestellungen, aber nur wenn sie existiert.
----------------------------------------------------------

-- Neue Spalte zu einer bestehenden Tabelle hinzufügen
ALTER TABLE kunden ADD COLUMN telefon VARCHAR(30);
-- ALTER 👉 bedeutet: verändern / ändern
-- ADD 👉 bedeutet: hinzufügen
-- COLUMN 👉 bedeutet: Spalte
-- VARCHAR(30) 👉 Datentyp: Text max. 30 Zeichen
-- Übersetzt: 
-- Füge der Tabelle kunden eine neue Spalte telefon hinzu.
----------------------------------------------------------

-- Spalte umbenennen
ALTER TABLE buecher RENAME COLUMN autor TO verfasser;
-- RENAME COLUMN 👉 bedeutet: Spalte umbenennen
-- TO 👉 bedeutet: zu
-- Übersetzt: 
-- Benenne die Spalte autor in verfasser um
----------------------------------------------------------

-- Spalte entfernen
ALTER TABLE kunden DROP COLUMN telefon;
-- Übersetzt: 
-- Lösche die Spalte telefon aus der Tabelle kunden

— leitet einen Kommentar ein. Kommentare werden von SQL ignoriert und dienen nur der Lesbarkeit.


Daten abfragen: SELECT

Testdaten einfügen

Bevor wir abfragen können, brauchen wir Daten. Fügen Sie diese Beispieldatensätze in Ihre Datenbank ein (Block 5 erklärt INSERT im Detail — jetzt einfach ausführen):

-- SQL — Testdaten einfügen
INSERT INTO kunden (vorname, nachname, email, registriert) VALUES
  ('Anna',  'Müller',  'anna.mueller@example.com',  '2023-05-10'),
  ('Ben',   'Schmidt', 'ben.schmidt@example.com',   '2023-08-22'),
  ('Clara', 'Weber',   'clara.weber@example.com',   '2024-01-05'),
  ('David', 'Bauer',   'david.bauer@example.com',   '2024-02-18'),
  ('Eva',   'Koch',    'eva.koch@example.com',      '2024-03-01');

INSERT INTO buecher (titel, autor, preis, lagernd) VALUES
  ('Die Verwandlung',      'Franz Kafka',        9.90,  TRUE),
  ('Der Prozess',          'Franz Kafka',       12.50,  TRUE),
  ('Faust I',              'Johann W. Goethe',   8.00,  FALSE),
  ('Nathan der Weise',     'G. E. Lessing',      7.50,  TRUE),
  ('Im Westen nichts Neues','Erich M. Remarque', 11.00, TRUE);

INSERT INTO bestellungen (kunden_id, buch_id, bestelldatum) VALUES
  (1, 1, '2024-01-15'),
  (1, 3, '2024-02-10'),
  (2, 2, '2024-02-20'),
  (3, 5, '2024-03-05'),
  (4, 1, '2024-03-12'),
  (5, 4, '2024-03-20');

Grundstruktur von SELECT

SELECT ist der wichtigste SQL-Befehl. Er liest Daten aus einer Tabelle. Die grundlegende Struktur:

-- SQL — SELECT-Grundstruktur
SELECT spalte1, spalte2, ...   -- Welche Spalten?
FROM   tabellenname;           -- Aus welcher Tabelle?
-- SQL — Beispiele
-- Alle Spalten und alle Zeilen der Tabelle kunden anzeigen
SELECT * FROM kunden;

-- Nur bestimmte Spalten anzeigen
SELECT vorname, nachname, email FROM kunden;

-- Ergebnisse mit einem Alias (Spaltennamen umbenennen)
SELECT vorname AS 'Vorname', nachname AS 'Familienname' FROM kunden;

Das Sternchen (*) steht für alle Spalten. Im Alltag ist es besser, konkrete Spaltennamen zu nennen — das macht Abfragen lesbarer und effizienter.

Berechnungen und Funktionen im SELECT

-- SQL — Berechnungen
-- Preis mit 19% Mehrwertsteuer berechnen
SELECT titel, preis, ROUND(preis * 1.19, 2) AS brutto_preis
FROM buecher;

-- Vor- und Nachname in einer Spalte zusammenführen
SELECT CONCAT(vorname, ' ', nachname) AS vollstaendiger_name
FROM kunden;
FunktionBeschreibung
ROUND(x, n)Rundet x auf n Dezimalstellen
CONCAT(a, b, …)Verbindet Textwerte aneinander
UPPER(s)Wandelt Text in Großbuchstaben um
LOWER(s)Wandelt Text in Kleinbuchstaben um
LENGTH(s)Gibt die Anzahl der Zeichen zurück
NOW()Aktuelles Datum und Uhrzeit

Aggregatfunktionen

Aggregatfunktionen rechnen über mehrere Zeilen hinweg und geben einen einzigen Wert zurück:

-- SQL — Aggregatfunktionen
-- Anzahl aller Bücher
SELECT COUNT(*) AS anzahl_buecher FROM buecher;

-- Durchschnittspreis aller Bücher
SELECT AVG(preis) AS durchschnittspreis FROM buecher;

-- Günstigstes und teuerstes Buch
SELECT MIN(preis) AS guenstigster, MAX(preis) AS teuerster FROM buecher;

-- Gesamtwert aller Bücher im Lager
SELECT SUM(preis) AS gesamtwert FROM buecher;

Filtern, Sortieren, Gruppieren

WHERE — Ergebnisse filtern

Mit WHERE legen Sie Bedingungen fest, welche Zeilen zurückgegeben werden. Nur Zeilen, für die die Bedingung wahr ist, erscheinen im Ergebnis.

-- SQL — WHERE-Beispiele
-----------------------------------------------------

-- Alle vorrätigen Bücher
SELECT * FROM buecher WHERE lagernd = TRUE;
-- Übersetzt:
-- Hole alle Daten aus der Tabelle buecher, 
-- aber nur von Büchern, die lagernd/im Lager sind.
-----------------------------------------------------

-- Bücher unter 10 Euro
SELECT titel, preis FROM buecher WHERE preis < 10.00;
-- Übersetzt:
-- Zeige Titel und Preis aller Bücher, die weniger als 10 € kosten.
-----------------------------------------------------

-- Bücher von Kafka
SELECT titel FROM buecher WHERE autor = 'Franz Kafka';
-- Übersetzt: Zeige die Titel aller Bücher von Franz Kafka.
-----------------------------------------------------

-- Kunden, die sich 2024 registriert haben
SELECT vorname, nachname FROM kunden
WHERE registriert >= '2024-01-01';
-- Übersetzt:
-- Zeige Vor- und Nachname aller Kunden, die seit 2024 registriert sind.
OperatorBedeutung
=Gleich
<> oder !=Ungleich
< / > / <= / >=Kleiner / Größer / Kleiner-gleich / Größer-gleich
BETWEEN a AND bZwischen a und b (beide Grenzen eingeschlossen)
IN (a, b, c)Ist einer der aufgeführten Werte
LIKE ‚Muster‘Textmuster: % steht für beliebig viele Zeichen, _ für genau ein Zeichen
IS NULL / IS NOT NULLIst leer / Ist nicht leer
-- SQL — Mehrere Bedingungen
---------------------------------------------------

-- AND: Beide Bedingungen müssen zutreffen
SELECT titel, preis FROM buecher
WHERE preis < 10.00 AND lagernd = TRUE;
-- Übersetzt:
-- Selektiere die Spalten titel und preis aus der Tabelle buecher, 
-- in der preis kleiner als 10.00 ist und lagernd gleich TRUE wahr ist.
---------------------------------------------------

-- OR: Mindestens eine Bedingung muss zutreffen
SELECT * FROM kunden
WHERE nachname = 'Müller' OR nachname = 'Schmidt';
-- Übersetzt:
-- Selektiere alle Spalten aus der Tabelle kunden, 
-- in der nachname gleich 'Müller' oder nachname gleich 'Schmidt' ist.
---------------------------------------------------

-- LIKE: Namen, die mit 'A' beginnen
SELECT * FROM kunden WHERE vorname LIKE 'A%';
-- WHERE vorname LIKE 'A%' → „nur Kunden, deren Vorname mit A beginnt
-- Bedeutet: LIKE & %:
-- % = beliebige Zeichen danach
-- 'A%' = alle Namen, die mit „A“ starten, z. B. „Anna“, „Andreas“
-- Übersetzt:
-- Zeige alle Daten von Kunden, deren Vorname mit A beginnt.“
---------------------------------------------------

-- BETWEEN: Bücher zwischen 8 und 11 Euro
SELECT titel, preis FROM buecher
WHERE preis BETWEEN 8.00 AND 11.00;
-- Übersetzt:
-- Selektiere die Spalten titel und preis aus der Tabelle buecher, 
-- in der preis zwischen 8.00 und 11.00 liegt

ORDER BY — Ergebnisse sortieren

ORDER BY sortiert die Ergebnisse nach einer oder mehreren Spalten. ASC steht für aufsteigend (Standard), DESC für absteigend.

-- SQL — Sortieren
---------------------------------------------------

-- Bücher nach Preis aufsteigend sortieren
SELECT titel, preis FROM buecher ORDER BY preis ASC;
-- ORDER BY → sortiere nach
-- ASC → Ascending = aufsteigend
-- Übersetzt:
-- Selektiere die Spalten titel und preis aus der Tabelle buecher, 
-- sortiere nach preis aufsteigend.
---------------------------------------------------

-- Kunden nach Nachnamen alphabetisch, dann nach Vornamen
SELECT vorname, nachname FROM kunden
ORDER BY nachname ASC, vorname ASC;
-- Übersetzt:
-- Selektiere die Spalten vorname und nachname aus der Tabelle kunden, 
-- sortiere nach nachname aufsteigend und danach nach vorname aufsteigend.
---------------------------------------------------

-- Neueste Registrierungen zuerst
SELECT * FROM kunden ORDER BY registriert DESC;
-- DESC → Descending = absteigend
-- Übersetzt:
-- Selektiere alle Spalten aus der Tabelle kunden, 
-- sortiere nach registriert absteigend.

LIMIT — Anzahl der Ergebnisse begrenzen

-- SQL — LIMIT
---------------------------------------------------

-- Nur die 3 teuersten Bücher anzeigen
SELECT titel, preis FROM buecher
ORDER BY preis DESC
LIMIT 3;
-- DESC → „Descending“ = „absteigend“
-- LIMIT → „begrenze auf“ / „nur die ersten“
-- Übersetzt:
-- Selektiere die Spalten titel und preis aus der Tabelle buecher, 
-- sortiere nach preis absteigend und zeige nur die ersten 3 Zeilen.
---------------------------------------------------

-- Ergebnisse 4–6 anzeigen (für Seitennavigation)
SELECT * FROM kunden
ORDER BY nachname ASC
LIMIT 3 OFFSET 3;
-- OFFSET → „überspringe die ersten“
-- Übersetzt:
-- Selektiere alle Spalten aus der Tabelle kunden, 
-- sortiere nach nachname aufsteigend, zeige 3 Zeilen, 
-- nachdem die ersten 3 Zeilen übersprungen wurden.

OFFSET gibt an, wie viele Datensätze am Anfang übersprungen werden — nützlich für die seitenweise Ausgabe von Daten.

GROUP BY — Ergebnisse gruppieren

GROUP BY fasst Zeilen mit gleichem Wert in einer Spalte zusammen. Es wird meist mit Aggregatfunktionen kombiniert.

-- SQL — GROUP BY
---------------------------------------------------

-- Anzahl Bücher pro Autor
SELECT autor, COUNT(*) AS anzahl
FROM buecher
GROUP BY autor;
-- COUNT(*) → „zähle alle Zeilen“ / „Anzahl der Einträge“
-- COUNT(*) → zählt alle Zeilen in der Gruppe
-- AS → „als“ / „benenne als“
-- GROUP BY → „gruppiere nach“
-- Übersetzt:
-- Selektiere die Spalten autor und die Anzahl aller Zeilen 
-- als anzahl aus der Tabelle buecher, 
-- gruppiere die Ergebnisse nach autor.
---------------------------------------------------

-- Durchschnittspreis pro Autor, nur wenn Durchschnitt > 9 Euro
SELECT autor, AVG(preis) AS durchschnitt
FROM buecher
GROUP BY autor
HAVING AVG(preis) > 9.00;
-- AS → „als“ / „benenne als“
-- AVG(preis) → „berechne den Durchschnitt von preis“
-- GROUP BY → „gruppiere nach“
-- HAVING → „nur Gruppen, bei denen…“ (Bedingung auf aggregierte Werte)
-- Übersetzt:
-- Selektiere die Spalten autor und den Durchschnitt 
-- von preis als durchschnitt aus der Tabelle buecher, 
-- gruppiere nach autor und zeige nur die Gruppen,
-- deren Durchschnittspreis größer als 9.00 ist.

COUNT(*) → zählt alle Zeilen in der Gruppe
AVG(preis) → berechnet den Durchschnitt von preis in der Gruppe
GROUP BY → gruppiert die Zeilen nach einem Feld
HAVING → filtert Gruppen nach aggregierten Werten (anders als WHERE, das einzelne Zeilen filtert)

WHERE vs. HAVING
WHERE filtert Zeilen, BEVOR sie gruppiert werden.
HAVING filtert Gruppen, NACHDEM sie gebildet wurden. Faustregel: WHERE wirkt auf einzelne Datensätze, HAVING auf Gruppen.

Die Reihenfolge der SQL-Klauseln
SELECT  →  FROM  →  WHERE  →  GROUP BY  →  HAVING  →  ORDER BY  →  LIMIT Diese Reihenfolge ist fest. Abweichungen führen zu einem Syntaxfehler.


Daten verändern: INSERT, UPDATE, DELETE

INSERT — Daten einfügen

INSERT fügt neue Datensätze in eine Tabelle ein. Sie benennen die Spalten und geben die entsprechenden Werte in derselben Reihenfolge an.

-- SQL — INSERT
---------------------------------------------------

-- Einen Datensatz einfügen
INSERT INTO kunden (vorname, nachname, email, registriert)
VALUES ('Finn', 'Lorenz', 'finn.lorenz@example.com', '2024-04-01');
-- INSERT INTO → „füge ein in / in die Tabelle einfügen“
-- VALUES → „mit den Werten“
-- Übersetzt:
-- Füge einen neuen Eintrag in die Tabelle kunden ein, 
-- mit vorname = 'Finn', nachname = 'Lorenz', 
-- email = 'finn.lorenz@example.com' und registriert = '2024-04-01'.
---------------------------------------------------

-- Mehrere Datensätze gleichzeitig einfügen
INSERT INTO buecher (titel, autor, preis, lagernd) VALUES
  ('Effi Briest',   'Theodor Fontane', 10.50, TRUE),
  ('Der Steppenwolf','Hermann Hesse',   11.90, TRUE);
-- Übersetzt:
-- Füge zwei neue Einträge in die Tabelle buecher ein:
-- titel = 'Effi Briest', autor = 'Theodor Fontane', preis = 10.50, lagernd = TRUE

INSERT INTO → Einfügen von Daten in eine Tabelle
VALUES → Werte, die in die Spalten eingefügt werden

Spalten mit DEFAULT oder AUTO_INCREMENT können weggelassen werden — das Datenbanksystem setzt den Wert automatisch.

UPDATE — Daten aktualisieren

UPDATE ändert bestehende Datensätze. Der WHERE-Teil bestimmt, welche Zeilen verändert werden.

-- SQL — UPDATE
---------------------------------------------------

-- Preis eines Buches anpassen
UPDATE buecher
SET preis = 13.50
WHERE id = 2;
-- UPDATE → „aktualisiere / ändere“
-- SET → „setze / weise zu“
-- WHERE → „nur dort, wo“
-- Übersetzt:
-- Aktualisiere die Tabelle buecher, setze preis auf 13.50 
-- nur bei der Zeile, in der id = 2 ist.
---------------------------------------------------

-- Mehrere Felder gleichzeitig ändern
UPDATE kunden
SET email = 'anna.m@beispiel.de', nachname = 'Maier'
WHERE id = 1;
-- Übersetzt:
-- Aktualisiere die Tabelle kunden, setze email auf 'anna.m@beispiel.de' 
-- und nachname auf 'Maier', nur bei der Zeile, in der id = 1 ist.
---------------------------------------------------

-- Alle nicht mehr vorrätigen Bücher markieren
UPDATE buecher SET lagernd = FALSE WHERE preis > 12.00;
-- Übersetzt:
-- Aktualisiere die Tabelle buecher, setze lagernd auf FALSE,
-- nur bei den Zeilen, in denen preis größer als 12.00 ist.

UPDATE [Tabelle] → Tabelle auswählen
SET [Spalten = Werte] → Spalten ändern
WHERE [Bedingung] → nur die Zeilen ändern, die die Bedingung erfüllen

Sicherheitshinweis: WHERE nicht vergessen!
Ein UPDATE ohne WHERE-Klausel verändert ALLE Datensätze in der Tabelle.
UPDATE buecher SET preis = 0;  <– Setzt ALLE Preise auf 0!
Prüfen Sie zuerst mit SELECT, welche Zeilen betroffen sein werden: SELECT * FROM buecher WHERE preis > 12.00;

DELETE — Daten löschen

-- SQL — DELETE
---------------------------------------------------

-- Einen Datensatz löschen
DELETE FROM buecher WHERE id = 3;
-- Lösche aus der Tabelle buecher die Zeile, in der id = 3 ist

-- Alle nicht vorrätigen Bücher löschen
DELETE FROM buecher WHERE lagernd = FALSE;
-- Lösche aus der Tabelle buecher alle Zeilen, in denen lagernd FALSE ist.

DELETE FROM [Tabelle] → Tabelle auswählen
WHERE [Bedingung] → nur Zeilen löschen, die die Bedingung erfüllen
Ohne WHERE → alle Zeilen werden gelöscht (Vorsicht!)

Sicherheitshinweis: DELETE ist endgültig
Ein DELETE ohne WHERE löscht ALLE Zeilen der Tabelle (die Tabelle selbst bleibt).
Gelöschte Daten können nicht wiederhergestellt werden. Auch hier: Testen Sie vorher mit SELECT, welche Zeilen betroffen sind.

TRUNCATE vs. DROP

DELETE FROM tabelle;Löscht alle Zeilen — aber die Tabelle bleibt erhalten
TRUNCATE TABLE tabelle;Löscht alle Zeilen effizienter — setzt AUTO_INCREMENT zurück
DROP TABLE tabelle;Löscht die Tabelle vollständig inklusive Struktur

Mehrere Tabellen verbinden: JOIN

Warum JOIN?

In relationalen Datenbanken werden Daten auf mehrere Tabellen aufgeteilt,
um Redundanzen zu vermeiden. Ein Kunde wird einmal in der Tabelle kunden gespeichert — seine Bestellungen in der Tabelle bestellungen, verknüpft über die kunden_id.
JOIN verbindet diese Tabellen für eine Abfrage.

INNER JOIN — nur übereinstimmende Datensätze

INNER JOIN gibt nur die Zeilen zurück, für die in beiden Tabellen ein übereinstimmender Wert in der Verknüpfungsspalte vorhanden ist.

-- SQL — INNER JOIN
---------------------------------------------------

-- Welcher Kunde hat welche Bestellung aufgegeben?
SELECT
  k.vorname,
  k.nachname,
  b.bestelldatum
FROM bestellungen AS b
INNER JOIN kunden AS k ON b.kunden_id = k.id;
-- INNER JOIN → „verbinde innerlich / nur Zeilen mit Übereinstimmung“
-- ON → „wo / auf Bedingung“

-- Selektiere die Spalten vorname und nachname aus der Tabelle kunden (Alias k) 
-- und die Spalte bestelldatum aus der Tabelle bestellungen (Alias b), 
-- verbinde bestellungen innerlich mit kunden, nur Zeilen, 
-- bei denen b.kunden_id gleich k.id ist.

INNER JOIN → verbindet zwei Tabellen, nur mit passenden Zeilen
AS [Alias] → Kurzname für die Tabelle, um die Schreibweise zu vereinfachen
ON [Bedingung] → Bedingung, nach der die Tabellen verbunden werden

AS b und AS k sind Aliase — kurze Namen für die Tabellen, die das Schreiben längerer Abfragen erleichtern. b.kunden_id = k.id ist die Verknüpfungsbedingung: Verknüpfe jede Bestellung mit dem Kunden, dessen id mit kunden_id übereinstimmt.

Drei Tabellen verbinden

-- SQL — Drei Tabellen verbinden
---------------------------------------------------

-- Komplette Bestellübersicht: Kunde, Buch, Datum
SELECT
  k.vorname,
  k.nachname,
  bu.titel,
  bu.preis,
  b.bestelldatum
FROM bestellungen AS b
INNER JOIN kunden   AS k  ON b.kunden_id = k.id
INNER JOIN buecher  AS bu ON b.buch_id   = bu.id
ORDER BY b.bestelldatum DESC;

-- Selektiere die Spalten vorname und nachname 
-- aus der Tabelle kunden (Alias k), titel 
-- und preis aus der Tabelle buecher (Alias bu) 
-- und bestelldatum aus der Tabelle bestellungen (Alias b),
-- verbinde bestellungen innerlich mit kunden über b.kunden_id = k.id,
-- verbinde bestellungen innerlich mit buecher über b.buch_id = bu.id, 
-- und sortiere die Ergebnisse nach b.bestelldatum absteigend.

INNER JOIN → verbindet Tabellen, nur passende Zeilen werden genommen
Aliases (AS) → Kurzname für Tabellen, um Schreibarbeit zu reduzieren
ON → Bedingung für die Verbindung
ORDER BYDESC → sortiere absteigend

LEFT JOIN — alle Datensätze der linken Tabelle

LEFT JOIN gibt alle Zeilen der linken Tabelle zurück, auch wenn es keine übereinstimmenden Zeilen in der rechten Tabelle gibt. Fehlende Werte werden als NULL angezeigt.

-- SQL — LEFT JOIN
---------------------------------------------------

-- Alle Kunden anzeigen, auch solche ohne Bestellung
SELECT
  k.vorname,
  k.nachname,
  b.bestelldatum
FROM kunden AS k
LEFT JOIN bestellungen AS b ON k.id = b.kunden_id
ORDER BY k.nachname;

-- Selektiere die Spalten vorname und nachname 
-- aus der Tabelle kunden (Alias k) und bestelldatum 
-- aus der Tabelle bestellungen (Alias b), verbinde kunden links 
-- mit bestellungen über k.id = b.kunden_id (alle Kunden werden angezeigt, 
-- auch wenn sie keine Bestellung haben), 
-- und sortiere die Ergebnisse nach k.nachname.

LEFT JOIN → alle Zeilen der linken Tabelle (kunden) bleiben erhalten, auch wenn keine passenden Zeilen in der rechten Tabelle (bestellungen) existieren.
Zeilen ohne passende Verbindung → NULL in den Spalten der rechten Tabelle.

Kunden ohne Bestellung erscheinen mit NULL in der Spalte bestelldatum. So lassen sich z. B. inaktive Kunden identifizieren.

JOIN-TypVerhalten
INNER JOINNur Zeilen, die in beiden Tabellen übereinstimmen
LEFT JOINAlle Zeilen der linken Tabelle + übereinstimmende der rechten (NULL wenn keine)
RIGHT JOINAlle Zeilen der rechten Tabelle + übereinstimmende der linken (NULL wenn keine)

Praxisbeispiele mit JOIN und Aggregation

-- SQL — Anzahl Bestellungen pro Kunde
SELECT
  k.vorname,
  k.nachname,
  COUNT(b.id) AS anzahl_bestellungen
FROM kunden AS k
LEFT JOIN bestellungen AS b ON k.id = b.kunden_id
GROUP BY k.id, k.vorname, k.nachname
ORDER BY anzahl_bestellungen DESC;
-- SQL — Umsatz pro Buch
SELECT
  bu.titel,
  bu.preis,
  COUNT(b.id)           AS mal_bestellt,
  COUNT(b.id) * bu.preis AS gesamtumsatz
FROM buecher AS bu
LEFT JOIN bestellungen AS b ON bu.id = b.buch_id
GROUP BY bu.id, bu.titel, bu.preis
ORDER BY gesamtumsatz DESC;

Vollständige SQL-Befehlsübersicht

Die nachfolgenden Blöcke enthalten alle hier verwendeten SQL-Befehle in einem Block — zum direkten Ausführen in phpMyAdmin.

-- KOMPLETTSKRIPT — Datenbank aufsetzen
-- 1. Datenbank anlegen
CREATE DATABASE IF NOT EXISTS shop
  CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
USE shop;

-- 2. Tabellen anlegen
CREATE TABLE kunden (
  id INT AUTO_INCREMENT PRIMARY KEY,
  vorname VARCHAR(100) NOT NULL,
  nachname VARCHAR(100) NOT NULL,
  email VARCHAR(255) NOT NULL UNIQUE,
  registriert DATE
);

CREATE TABLE buecher (
  id INT AUTO_INCREMENT PRIMARY KEY,
  titel VARCHAR(255) NOT NULL,
  autor VARCHAR(150) NOT NULL,
  preis DECIMAL(8,2) NOT NULL,
  lagernd BOOLEAN DEFAULT TRUE
);

CREATE TABLE bestellungen (
  id INT AUTO_INCREMENT PRIMARY KEY,
  kunden_id INT NOT NULL,
  buch_id INT NOT NULL,
  bestelldatum DATE,
  FOREIGN KEY (kunden_id) REFERENCES kunden(id),
  FOREIGN KEY (buch_id) REFERENCES buecher(id)
);

-- 3. Testdaten einfügen
INSERT INTO kunden (vorname, nachname, email, registriert) VALUES
  ('Anna','Müller','anna.mueller@example.com','2023-05-10'),
  ('Ben','Schmidt','ben.schmidt@example.com','2023-08-22'),
  ('Clara','Weber','clara.weber@example.com','2024-01-05'),
  ('David','Bauer','david.bauer@example.com','2024-02-18'),
  ('Eva','Koch','eva.koch@example.com','2024-03-01');

INSERT INTO buecher (titel, autor, preis, lagernd) VALUES
  ('Die Verwandlung','Franz Kafka',9.90,TRUE),
  ('Der Prozess','Franz Kafka',12.50,TRUE),
  ('Faust I','Johann W. Goethe',8.00,FALSE),
  ('Nathan der Weise','G. E. Lessing',7.50,TRUE),
  ('Im Westen nichts Neues','Erich M. Remarque',11.00,TRUE);

INSERT INTO bestellungen (kunden_id, buch_id, bestelldatum) VALUES
  (1,1,'2024-01-15'),
  (1,3,'2024-02-10'),
  (2,2,'2024-02-20');
Dieses Dokument teilen

SQL-Befehle – Datenbank

Oder Link kopieren

INHALT

Abonnieren

×
Cancel