CREATE VIEW – die Abfrage, die du nur einmal schreibst
Wenn dieselbe 15-zeilige Abfrage an vier Stellen im Code steht, ändert man sie irgendwann an dreien. Eine View gibt ihr einen Namen – danach steht sie nur noch an einer Stelle.
Es gibt in jedem Projekt diese eine Abfrage, die überall gebraucht wird. Bei mir sieht sie ungefähr so aus:
SELECT r.id, r.nummer, r.betrag_cent, r.faellig_am, k.name AS kunde
FROM rechnungen r
JOIN kunden k ON k.id = r.kunde_id
WHERE r.storniert = 0
AND NOT EXISTS (SELECT 1 FROM zahlungen z WHERE z.rechnung_id = r.id)„Offene Rechnungen". Die steht dann im Dashboard, im Export, in der Mahnungsliste und im Monatsbericht — vier Kopien. Und wenn irgendwann Teilzahlungen dazukommen, ändert man sie an dreien.
Gib ihr einen Namen
CREATE VIEW offene_rechnungen AS
SELECT r.id, r.nummer, r.betrag_cent, r.faellig_am, k.name AS kunde
FROM rechnungen r
JOIN kunden k ON k.id = r.kunde_id
WHERE r.storniert = 0
AND NOT EXISTS (SELECT 1 FROM zahlungen z WHERE z.rechnung_id = r.id);Ab jetzt ist das eine Tabelle — jedenfalls fühlt es sich so an:
SELECT * FROM offene_rechnungen ORDER BY faellig_am;
SELECT kunde, SUM(betrag_cent) AS summe
FROM offene_rechnungen
GROUP BY kunde
ORDER BY summe DESC;
SELECT COUNT(*) FROM offene_rechnungen WHERE faellig_am < date('now');Drei völlig verschiedene Auswertungen, und die Definition von „offen" steht genau einmal in der Datenbank.
Was eine View ist – und was nicht
Eine View speichert keine Daten. Sie ist ein gespeicherter Name für eine Abfrage. Jedes Mal, wenn du sie benutzt, führt die Datenbank die dahinterliegende Abfrage aus. Das heißt:
- Sie ist immer aktuell — es gibt nichts, das veralten könnte.
- Sie ist nicht schneller. Wenn die zugrundeliegende Abfrage langsam ist, ist die View es auch. Der Gewinn liegt in der Wartbarkeit, nicht in der Geschwindigkeit.
In SQLite sind Views außerdem schreibgeschützt: INSERT INTO offene_rechnungen … geht nicht. Das ist meist genau richtig — eine View ist zum Auswerten da.
Wo sie mir am meisten hilft
Nicht beim Sparen von Tipparbeit, sondern beim Festhalten einer Definition. „Offen", „aktiv", „diesen Monat", „hat gekündigt" — das sind fachliche Begriffe, über die man mit Kunden spricht. Wenn sie an vier Stellen leicht unterschiedlich implementiert sind, kommen im Dashboard und im Bericht verschiedene Zahlen heraus. Und dann diskutiert man eine Stunde über eine Zahl, statt über das Geschäft.
Eine View macht daraus eine einzige, nachlesbare Wahrheit.
Ändern und aufräumen
Es gibt kein ALTER VIEW. Man wirft sie weg und legt sie neu an:
DROP VIEW IF EXISTS offene_rechnungen;
CREATE VIEW offene_rechnungen AS …;Das gehört bei mir in dieselbe Schema-Migration wie Tabellenänderungen — sonst zeigt die View nach einer Spaltenumbenennung ins Leere, und der Fehler taucht erst auf, wenn jemand den Monatsbericht öffnet.
Und wenn ich Parameter brauche?
Views nehmen keine Parameter. Wenn du „offene Rechnungen eines Kunden" willst, filterst du außen:
SELECT * FROM offene_rechnungen WHERE kunde = ?;Das ist völlig ausreichend — die Datenbank zieht die Bedingung beim Ausführen in die Abfrage hinein.
Du hast ein Projekt, in dem dieselbe Auswertung an mehreren Stellen leicht unterschiedliche Zahlen liefert? Das ist ein klassisches Symptom. Schreib mir.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
WITH RECURSIVE – Kategoriebäume und Kommentar-Threads in einer einzigen Abfrage
Kategorien mit Unterkategorien, Kommentare mit Antworten, Ordner in Ordnern: Die meisten holen sich so etwas mit einer Schleife und einer Abfrage pro Ebene. Eine rekursive CTE holt den ganzen Baum in einem Rutsch – inklusive Tiefe und Pfad.
UNION vs. UNION ALL – zwei Abfragen zusammenlegen, ohne Zeilen zu verlieren
UNION entfernt Duplikate. Das klingt hilfreich, kostet aber eine komplette Sortierung – und wirft dir stillschweigend echte Zeilen weg, die zufällig identisch aussehen. UNION ALL ist fast immer die richtige Wahl.
JSON in SQLite abfragen – json_extract und der ->>-Operator
Ein JSON-Feld in der Datenbank ist bequem, bis man danach filtern will. SQLite kann direkt hineinschauen – und mit einem Index auf dem richtigen Ausdruck ist das sogar schnell.