- 1 Section
- 10 Lessons
- unbegrenzt
- SQL Fortgeschritten10
- 1.1Alle JOIN-Typen: RIGHT, FULL OUTER, CROSS, SELF
- 1.2Unterabfragen (Subqueries)
- 1.3Common Table Expressions (CTEs)
- 1.4Window Functions: ROW_NUMBER, RANK, PARTITION BY
- 1.5Views erstellen und nutzen
- 1.6Stored Procedures und Funktionen
- 1.7Trigger
- 1.8Datenbankindizes und Query-Optimierung
- 1.9Datenbankreporte und komplexe Auswertungen
- 1.10SQL-Fortgeschrittenenaufgaben
Views erstellen und nutzen
Eine View ist eine in der Datenbank gespeicherte, virtuelle Tabelle. Sie speichert keine Daten selbst, sondern nur eine SELECT-Abfrage. Wenn du die View abfragst, führt die Datenbank im Hintergrund diese Abfrage aus und liefert das Ergebnis – so, als hättest du eine echte Tabelle abgefragt.
Views machen drei Dinge richtig gut: sie vereinfachen komplexe Abfragen, sie kapseln Geschäftslogik (Filter, Berechnungen) hinter einem festen Namen und sie schränken den Datenzugriff ein (Anwender sieht nur das, was die View liefert). Diese Lektion zeigt dir alle drei Anwendungen.
1) Die Grundidee
Stell dir vor, du brauchst regelmäßig diese Abfrage:
SELECT k.name, k.ort, SUM(b.summe) AS umsatz FROM kunden k LEFT JOIN bestellungen b ON k.id = b.kunde_id GROUP BY k.id, k.name, k.ort;
Statt sie immer wieder zu tippen, speicherst du sie einmalig als View:
CREATE VIEW v_kundenumsatz AS SELECT k.name, k.ort, SUM(b.summe) AS umsatz FROM kunden k LEFT JOIN bestellungen b ON k.id = b.kunde_id GROUP BY k.id, k.name, k.ort;
Danach kannst du die View wie eine normale Tabelle behandeln:
SELECT * FROM v_kundenumsatz WHERE umsatz > 500;
Im Hintergrund führt die DB die ursprüngliche SELECT-Abfrage aus und filtert dann. Du musst die komplexe Logik nicht mehr kennen – sie steckt in der View.
2) Wie Views technisch funktionieren
Eine View speichert keine Daten, sondern nur die SQL-Definition (außer bei materialisierten Views, siehe unten). Bei jeder Abfrage wird die Definition ausgeführt:
SELECT * FROM v_kundenumsatz ab – weiß nicht, was darunter passiert.v_kundenumsatz (virtuell)kunden, bestellungen3) Beispiel-Daten für diese Lektion
| id | name | ort |
|---|---|---|
| 1 | Anna | Berlin |
| 2 | Ben | München |
| 3 | Carla | Berlin |
| 4 | Dirk | München |
| kunde_id | summe |
|---|---|
| 1 | 500 |
| 1 | 200 |
| 2 | 1200 |
| 3 | 800 |
4) View erstellen, abfragen, ändern, löschen
Die wichtigsten Befehle:
-- Erstellen CREATE VIEW v_top_kunden AS SELECT k.name, SUM(b.summe) AS umsatz FROM kunden k JOIN bestellungen b ON k.id = b.kunde_id GROUP BY k.id, k.name HAVING SUM(b.summe) > 500; -- Abfragen wie eine Tabelle SELECT * FROM v_top_kunden; -- Definition ändern (in den meisten DBs) CREATE OR REPLACE VIEW v_top_kunden AS SELECT ... ; -- Löschen DROP VIEW v_top_kunden; -- Sicheres Löschen (kein Fehler, wenn nicht vorhanden) DROP VIEW IF EXISTS v_top_kunden;
Konvention: View-Namen mit dem Präfix v_ oder vw_, damit sie in einer Datenbank von echten Tabellen unterscheidbar sind. Das ist keine Pflicht, aber gute Praxis.
5) Die drei Hauptanwendungen
Views sind ein vielseitiges Werkzeug. Drei typische Einsatzgebiete:
mitarbeiter enthält Gehalt. View v_mitarbeiter_oeffentlich zeigt nur Name und Abteilung – sensible Daten bleiben geschützt.6) Anwendung 1: Komplexität verbergen
Eine View kann die komplexeste Logik auf eine einfache Schnittstelle reduzieren:
CREATE VIEW v_dashboard AS SELECT k.ort, COUNT(DISTINCT k.id) AS anzahl_kunden, COUNT(b.kunde_id) AS anzahl_bestellungen, COALESCE(SUM(b.summe), 0) AS gesamtumsatz, ROUND(AVG(b.summe), 2) AS avg_bestellwert FROM kunden k LEFT JOIN bestellungen b ON k.id = b.kunde_id GROUP BY k.ort;
Wer auswerten will, schreibt nur noch SELECT * FROM v_dashboard ORDER BY gesamtumsatz DESC; – fertig. Die JOIN-/GROUP-Logik bleibt in der View.
7) Anwendung 2: Zugriffsbeschränkung
Sicherheits-Klassiker: ein bestimmter Benutzer (z. B. eine Reporting-Anwendung) soll Kundendaten sehen, aber keine sensiblen Felder:
CREATE VIEW v_kunden_oeffentlich AS SELECT id, name, ort FROM kunden; -- Spalten wie email, telefon, geburtsdatum werden NICHT exponiert GRANT SELECT ON v_kunden_oeffentlich TO reporting_user; -- Auf die Basis-Tabelle hat reporting_user KEIN Recht
Der Reporting-User kann jetzt nur v_kunden_oeffentlich abfragen, nicht die volle kunden-Tabelle. Die sensiblen Spalten existieren weiter, sind aber nicht zugänglich.
Auch Zeilen-basierte Filter sind möglich: eine View, die nur die Daten einer Filiale zeigt, oder nur Bestellungen aus dem aktuellen Jahr:
CREATE VIEW v_bestellungen_aktuell AS SELECT * FROM bestellungen WHERE bestelldatum >= '2026-01-01';
8) Anwendung 3: Abstraktion bei Schema-Änderungen
Stell dir vor, eine alte Anwendung erwartet eine Tabelle kunde mit Spalten vorname und nachname. Im neuen Schema heißt sie kunden und hat nur eine Spalte name. Eine View überbrückt das:
CREATE VIEW kunde AS SELECT id, SPLIT_PART(name, ' ', 1) AS vorname, SPLIT_PART(name, ' ', 2) AS nachname, ort FROM kunden;
Die alte Anwendung sieht weiter „ihre" Tabelle, das physische Schema kann sich aber modernisieren. Solche Migrations-Views sind ein verbreitetes Muster bei größeren Refactorings.
9) Aktualisierbare Views
Eine View ist nicht nur lesbar – unter bestimmten Bedingungen kannst du sie auch mit INSERT, UPDATE und DELETE verändern. Solche Views heißen updatable views.
Bedingungen für die Aktualisierbarkeit (je nach DB unterschiedlich, hier MySQL-Regeln vereinfacht):
- Nur eine Basistabelle (kein JOIN)
- Keine Aggregate (
SUM,COUNT,AVG…) - Kein
GROUP BY,DISTINCT,HAVING - Keine Subquery in der
SELECT-Liste - Keine
UNION
-- aktualisierbar: einfacher Filter über eine Tabelle CREATE VIEW v_berlin_kunden AS SELECT id, name FROM kunden WHERE ort = 'Berlin'; -- Das funktioniert: UPDATE v_berlin_kunden SET name = 'Anna M.' WHERE id = 1;
UPDATE theoretisch eine Zeile aus der View „herauseditieren" (z. B. ort auf 'München' setzen, dann verschwindet die Zeile aus der Berlin-View). Mit WITH CHECK OPTION verbietet die DB Änderungen, die das View-Kriterium verletzen würden.
CREATE VIEW v_berlin_kunden AS SELECT id, name, ort FROM kunden WHERE ort = 'Berlin' WITH CHECK OPTION; -- Versucht jetzt jemand UPDATE … SET ort='München', kommt ein Fehler
10) View vs. Tabelle vs. CTE vs. materialisierte View
dauerhaft ✓
schreibbar ✓
dauerhaft ✓
eingeschränkt schreibbar
dauerhaft ✗
schreibbar ✗
dauerhaft ✓
nicht direkt schreibbar
11) Materialized Views
Eine Materialized View ist eine View, deren Ergebnis tatsächlich auf der Festplatte gespeichert wird – wie bei einer echten Tabelle. Beim Zugriff wird nichts neu berechnet, sondern direkt aus dem gespeicherten Ergebnis gelesen.
Vorteil: bei aufwendigen Abfragen (mehrere JOINs, große Aggregate) extrem schneller Zugriff. Nachteil: das gespeicherte Ergebnis ist nicht automatisch aktuell. Wenn sich die Basis-Tabellen ändern, muss die Materialized View neu aufgebaut werden:
-- PostgreSQL-Syntax CREATE MATERIALIZED VIEW mv_kundenumsatz AS SELECT k.name, SUM(b.summe) AS umsatz FROM kunden k LEFT JOIN bestellungen b ON k.id = b.kunde_id GROUP BY k.id, k.name; -- Neuberechnung anstoßen (z. B. nächtlich per Cronjob) REFRESH MATERIALIZED VIEW mv_kundenumsatz;
INSERT INTO … SELECT aktualisiert wird. PostgreSQL, Oracle und SQL Server unterstützen Materialized Views nativ.
12) Performance-Verhalten von Views
Häufiges Missverständnis: „Views sind schnell, weil sie vorbereitet sind." Das stimmt nur für Materialized Views. Bei normalen Views passiert bei jedem Zugriff:
- Die Datenbank löst die View-Referenz auf und setzt die
SELECT-Definition ein - Das Ergebnis ist eine größere Abfrage, die normal optimiert wird
- Indizes der Basis-Tabellen werden genutzt
Konsequenz: eine View ist nicht langsamer und nicht schneller als die zugrunde liegende Abfrage. Sie ist nur lesbarer/wiederverwendbarer. Wer Performance-Probleme hat, muss bei den Basis-Tabellen ansetzen – etwa mit Indizes (siehe L8).
13) Views auf Views
Du kannst Views auf bestehenden Views aufbauen:
CREATE VIEW v_basis AS SELECT k.id, k.name, k.ort, SUM(b.summe) AS umsatz FROM kunden k LEFT JOIN bestellungen b ON k.id = b.kunde_id GROUP BY k.id, k.name, k.ort; CREATE VIEW v_berlin_top AS SELECT * FROM v_basis WHERE ort = 'Berlin' AND umsatz > 500;
Das ist erlaubt, aber Vorsicht: tiefere Schichten machen es schwierig nachzuvollziehen, woher Daten kommen. Faustregel: maximal 2 Ebenen. Bei mehr ist meist eine Refaktorisierung sinnvoll.
14) Häufige Fehler bei Views
- Spaltennamen nicht aliased: berechnete Spalten wie
SUM(b.summe)brauchen einen Alias (AS umsatz), sonst hat die View eine kryptische Spalte - ORDER BY in der View: ist in vielen DBs erlaubt, aber unsinnig – wenn die View dann mit einem eigenen
ORDER BYabgefragt wird, geht das innere verloren. Sortierung gehört in die finale Abfrage - Vergessene Berechtigungen: nach
CREATE VIEWbrauchen andere Benutzer ein explizitesGRANT SELECT, sonst sehen sie die View nicht - Schema-Drift: wenn jemand eine Spalte der Basis-Tabelle löscht, brechen alle Views, die sie nutzen – am besten beim Refactoring alle Views prüfen
- SELECT * in View-Definitionen: bei späterem Spalten-Add in der Basis-Tabelle bekommt die View die neue Spalte nicht automatisch. Spalten besser explizit auflisten
15) View-Konventionen
Best Practices in größeren Projekten:
- Präfix:
v_odervw_für Views,mv_für Materialized Views - Sprechende Namen:
v_kunden_mit_offenen_rechnungenstattv_kunden2 - Eine View, eine Aufgabe: nicht versuchen, eine View für alle Fragen zu bauen – lieber mehrere spezialisierte
- Spalten explizit auflisten: nie
SELECT *in einer View-Definition - Kommentare in der DB hinterlegen (
COMMENT ON VIEW …in PostgreSQL/Oracle) - Versionierung: View-Definitionen in das DB-Migrationssystem (Flyway, Liquibase) aufnehmen, nicht nur manuell anlegen
CREATE VIEW … AS SELECT …) und der Unterschied zwischen View und Materialized View sind klassische Klausurthemen.
Zusammenfassung
Eine View ist eine in der Datenbank gespeicherte SELECT-Abfrage, die wie eine Tabelle abgefragt werden kann. Sie speichert keine Daten selbst, sondern wird bei jedem Zugriff neu ausgewertet. Drei Hauptanwendungen: Komplexität verbergen (JOINs/Aggregate hinter einem Namen), Zugriff einschränken (sensible Spalten ausblenden) und als Abstraktionsschicht bei Schema-Änderungen. Mit CREATE VIEW erstellen, mit DROP VIEW löschen, mit CREATE OR REPLACE VIEW ändern. Einfache Views sind aktualisierbar; mit WITH CHECK OPTION verhindert man, dass UPDATEs das View-Kriterium verletzen. Materialized Views speichern das Ergebnis physisch – schnell beim Lesen, brauchen aber regelmäßige Aktualisierung (in MySQL nicht nativ verfügbar).
