Wer in einem 200-Zeilen-SELECT-Statement nicht erkennen kann, wo die WHERE-Klausel anfängt und wo sie aufhört, hat ein Strukturproblem — kein Inhaltsproblem. Dieser Artikel zeigt, wie man SQL-Statements so formatiert, dass SELECT, FROM, WHERE und JOIN auch in langen Abfragen sofort erkennbar bleiben.
→ Teil einer Reihe. Dieser Artikel ist Teil 2 und behandelt den Statement-Aufbau (
SELECT,WHERE,FROM,JOIN). Die Bezeichner-, Delimiter-, Komma- und Alias-Grundlagen stehen in Teil 1 — Bezeichner, Delimiter, Kommata, Aliase.
TL;DR — was dieser Artikel liefert:
- Hauptelemente (
SELECT,FROM,WHERE,GROUP BY,HAVING,ORDER BY) gehören in separate Zeilen mit konsistenter Einrückung. WHERE-Klausel — Operanden und Operatoren spaltenartig ausrichten, gleichwertige Bedingungen gleich eingerückt. Die Klammer-Struktur wird so visuell lesbar.FROM-Klausel — Tabelle direkt hinter demJOIN-Operator,ON-Schlüsselwort in eigene Zeile,JOIN-Bedingungen wie eine Mini-WHERE-Klausel.- Postgres-Brücke + Auto-Formatter am Ende —
[brackets]vs."quotes",DISTINCT ON,LATERAL. sqlfluff und pgFormatter ergänzen die manuelle Disziplin, sie ersetzen sie nicht.
Voraussetzung: SSMS oder ein anderer SQL-Editor mit konfigurierbarer Tab-Weite reicht. Eine lebende AdventureWorks-Datenbank ist nicht erforderlich — die Beispiele zeigen Pattern, keine ausführbaren Pipelines.
Inhalt
- Allgemeines zur Einrückung
- Grundlegende Sprachelemente
- SELECT Feldliste
- WHERE-Klausel
- FROM-Klausel
- GROUP BY, HAVING, ORDER BY
- Auto-Formatter und „Formatieren ist Lernen“
- Postgres-Brücke
- Fazit
- FAQ
- Verwandte Artikel
Allgemeines zur Einrückung
Ein Analogon zur SQL-Struktur ist die Gliederung eines Inhaltsverzeichnisses. Die folgende eingerückte Version ist gegenüber der flachen Variante (siehe weiter unten) deutlich schneller zu erfassen:
1. Kapitel der ersten Ebene
1.1. Kapitel der zweiten Ebene
1.1.1. Kapitel der dritten Ebene
1.1.2. Kapitel der dritten Ebene
1.2. Kapitel der zweiten Ebene
2. Kapitel der ersten Ebene
2.1. Kapitel der zweiten Ebene
2.1.1. Kapitel der dritten Ebene
Zum Vergleich folgt dasselbe Inhaltsverzeichnis ohne Einrückung:
1. Kapitel der ersten Ebene
1.1. Kapitel der zweiten Ebene
1.1.1. Kapitel der dritten Ebene
1.1.2. Kapitel der dritten Ebene
1.2. Kapitel der zweiten Ebene
2. Kapitel der ersten Ebene
2.1. Kapitel der zweiten Ebene
2.1.1. Kapitel der dritten Ebene
Linksbündig ausgerichtete Inhaltsverzeichnisse funktionieren auch, dann allerdings nur mit zusätzlichen Formatierungs-Optionen wie Groß-/Klein-Schreibung, Fett oder Kursiv für die unterschiedlichen Ebenen. Im SQL-Editor sind solche Optionen typischerweise nicht verfügbar (SSMS rendert Plain-Text mit Syntax-Highlighting, kein Fett für Bezeichner). Daher bleibt als strukturierendes Mittel die Einrückung.
Eine Einordnung vorab: Alle Layout-Regeln dieses Artikels sind Formatierungs-Konventionen. SQL erzwingt weder Zeilenumbrüche noch Einrückung oder die Position von Kommas und Schlüsselwörtern. Die Konventionen zielen darauf, die Struktur eines Statements sichtbar zu machen, bevor man es liest.
Grundlegende Sprachelemente
EDieser Artikel betrachtet die sechs zentralen Klauseln eines SELECT-Statements:
SELECT FROM WHERE GROUP BY HAVING ORDER BY
Ein vollständiges SELECT-Statement kann weitere Klauseln enthalten (WITH, TOP bzw. LIMIT, OFFSET/FETCH, Window-Definitionen) — für sie gelten dieselben Einrückungs-Prinzipien. Behandelt man die sechs Klauseln als erste Ebene, stehen ihre Inhalte eine Einrückungsebene tiefer. Daraus ergibt sich die folgende grundlegende Struktur eines SQL-Statements:
1: SELECT
2: Feldliste
3: FROM
4: Datenquellen
5: WHERE
6: Bedingungen auf Datenquelle
7: GROUP BY
8: Gruppierungsfelder
9: HAVING
10: Bedingungen auf Aggregationen
11: ORDER BY
12: Sortier-Felder
Die Grundregel dieses Style-Guides lautet: Die Hauptelemente eines SQL-Statements stehen in separaten Zeilen.
Zur Abgrenzung folgen zwei Beispiele für Formatierungen, die häufig zu finden sind und diese klare Strukturierung nicht berücksichtigen. In beiden Beispielen muss man das Statement zumindest in Teilen lesen, um zu erfassen, wo ein Hauptelement beginnt und wo es aufhört.
Linksbündige Ausrichtung von Haupt- und Unterelementen
Gelegentlich findet man, dass Elemente der obersten Ebene und die Elemente der nächsten Ebene gleichermaßen eingerückt sind. Das sieht man besonders häufig in der FROM-Klausel: Die Datenquellen (Tabellen, Views, CTEs) sind genauso eingerückt wie das einleitende Schlüsselwort FROM:
1: SELECT
2: Feldliste
3: FROM
4: Tabelle1
5: JOIN Tabelle2 ON [...]
6: JOIN Tabelle3 ON [...]
7: WHERE
8: Bedingungen auf Datenquelle
9: GROUP BY
10: Gruppierungsfelder
11: HAVING
12: Bedingungen auf Aggregationen
13: ORDER BY
14: Sortier-Felder
Rechtsbündige Ausrichtung von Schlüsselwörtern
In diesem Beispiel sind die grundlegenden Klauseln des SELECT-Statements (ohne Berücksichtigung des Schlüsselwortes BY) rechtsbündig ausgerichtet. Diese Art der Einrückung macht die Ausrichtung zusätzlich aufwendiger, weil man mit unterschiedlich starken Einrückungen arbeiten muss.
1: SELECT Feld1, Feld2, Feld3
2: FROM Tabelle1
3: LEFT JOIN Tabelle2 ON [...]
4: LEFT JOIN Tabelle3 ON [...]
5: WHERE Bedingung1
6: OR Bedingung2
7: OR Bedingung3
8: GROUP BY Gruppierungsfelder
9: HAVING Bedingung1
10: OR Bedingung2
11: OR Bedingung3
12: ORDER BY Sortier-Felder
SELECT Feldliste
Die natürliche Leserichtung eines SQL-Statements ist von links nach rechts und von oben nach unten. Mit Tastatur und Maus geht die vertikale Navigation um einiges leichter als die horizontale Navigation. Das Mausrad und die Bild auf/Bild ab-Tasten erlauben eine schnelle vertikale Navigation auch innerhalb langer komplexer Statements, wenn Feldlisten untereinander geschrieben werden. Der wichtigere Effekt ist editor-unabhängig: Eine Zeile pro Ausdruck macht lange Feldlisten scanbar und erleichtert es, einzelne Ausdrücke zu vergleichen, zu verschieben oder zu ergänzen.
Feldnamen sollten daher als vertikale Liste mit vorangestellten Kommas geschrieben werden — die ausführliche Begründung (Komma-Lesbarkeit, Blockauswahl-Pattern) steht in Teil 1, Abschnitt „Das Komma“. Je Zeile ist nur ein Feld zu notieren. Da die Feldliste dem Schlüsselwort SELECT logisch untergeordnet ist, sind die Feldnamen entsprechend der vereinbarten Einrückungsweite einzurücken.
1: SELECT
2: Feld1
3: ,Feld2
4: ,Feld3
5: FROM [...]
6: WHERE [...]
7: GROUP BY
8: Feld1
9: ,Feld2
10: ,Feld3
11: HAVING [...]
12: ORDER BY
13: Feld1
14: ,Feld2
15: ,Feld3
WHERE-Klausel
Die Reihenfolge folgt hier bewusst nicht der SQL-Syntax: Die WHERE-Klausel führt zuerst in das zentrale Bedingungs-Pattern ein, das anschließend für die FROM– und HAVING-Klauseln wiederverwendet wird. Eine WHERE-Klausel enthält eine oder mehrere Bedingungen (Prädikate), die durch logische Operatoren verknüpft sind. Bei der Formatierung der Bedingungen sind zwei Punkte besonders zu berücksichtigen:
- Ausrichtung von Operanden
- Einrückung gleichwertiger Bedingungen
Ausrichtung von Operanden
Eine einfache Bedingung besteht aus zwei Operanden und einem Operator (=, !=, <>, IN, NOT IN etc.). In einem zusammengesetzten Ausdruck mit mehreren Einzel-Bedingungen sollten Operanden und Operatoren linksbündig untereinander ausgerichtet werden. Im folgenden Beispiel sind die Feldnamen unterschiedlich lang und es werden unterschiedliche Operatoren angewendet:
1: [...]
2: WHERE
3: T01.[Feld___1] = 'Irgendwas'
4: AND T01.[Feld__2] <> 1
5: AND T01.[Feld_____3] NOT IN (1, 2, 3)
6: AND T01.[Feld4] = T02.[Feld5]
So entsteht eine tabellenartige Notation, die schnelle visuelle Navigation innerhalb der Bedingungs-Bestandteile erlaubt.
Einrückung gleichwertiger Bedingungen
Enthält die WHERE-Klausel mehr als eine Bedingung, werden diese mit logischen Operatoren wie AND oder OR verknüpft. Klammern sind dann erforderlich, wenn die gewünschte logische Gruppierung von der Operator-Präzedenz abweicht (AND bindet stärker als OR). Auch darüber hinaus lohnen sie sich bei komplexen Ausdrücken für die Lesbarkeit. Je nach Komplexität des Gesamtausdrucks entstehen so tief verschachtelte Strukturen.
Um komplexe und verschachtelte Ausdrücke lesbar zu halten, sollte die Strukturierung und Formatierung einer WHERE-Klausel besondere Aufmerksamkeit bekommen: gleichwertige Bedingungen werden untereinander mit gleicher Einrückung notiert, eine logische Verknüpfung gleichwertiger Bedingungen bekommt eine Einrückung, die der Klammer-Hierarchie entspricht.
1: [...]
2: WHERE (
3: (
4: [Operand01] = [Operand02]
5: OR [Operand03] = [Operand05]
6: OR [Operand05] = [Operand06]
7: )
8: AND (
9: [Operand07] = [Operand08]
10: OR [Operand09] = [Operand10]
11: )
12: AND [Operand11] = [Operand12]
13: )
14: OR (
15: [Operand13] = [Operand14]
16: )
Die logischen Verknüpfungen werden bei dieser Einrückung visuell lesbar. Der folgende Screenshot derselben WHERE-Klausel in Notepad++ macht den Effekt noch deutlicher, weil das Editor-Feature der vertikalen Hilfslinien an den Tab-Stops die Klammer-Hierarchie unterstreicht:

FROM-Klausel
Wie bei den anderen Hauptelementen werden die untergeordneten Elemente der FROM-Klausel eingerückt notiert. In der Regel handelt es sich um Datenquellen — Tabellen, Views und Common Table Expressions (CTEs).
Sub-SELECTs in der FROM-Klausel lassen sich durch CTEs ersetzen, wenn die Unterabfrage einen eigenständigen logischen Schritt bildet, mehrfach gebraucht wird oder das Statement unübersichtlich macht: Eine CTE strukturiert es top-down. Bei kleinen, nur einmal verwendeten Unterabfragen ist die Derived Table oft die kompaktere Wahl. Der Umbau ist eine Strukturierungs-Entscheidung — wie die CTE ausgeführt wird, bestimmt der Optimizer der jeweiligen Engine. Was Postgres dabei anders macht (MATERIALIZED / NOT MATERIALIZED), steht im FAQ am Artikel-Ende.
Für die Formatierung einer JOIN-Klausel gibt es vier Bausteine:
- Tabelle (oder View / CTE)
JOIN-OperatorON-SchlüsselwortJOIN-Bedingung
Im folgenden Codebeispiel fehlt der visuelle Anker, um die Elemente der FROM-Klausel zu identifizieren:
1: FROM
2: Tabelle1 T01
3: JOIN Tabelle2 T02
4: ON T01.[FK] = T02.[ID]
5: JOIN Tabelle3 T03 ON
6: T02.[FK] = T03.[ID]
7: JOIN Tabelle4 T04
8: ON T03.[FK] = T04.[ID]
9: WHERE
10: [...]
Die Elemente der FROM-Klausel gehören der Lesbarkeit wegen in separate Zeilen. Ausnahme: die herangejointe Tabelle steht direkt hinter dem JOIN-Operator. Das ON-Schlüsselwort steht in diesem Style-Guide linksbündig zum JOIN-Operator in der folgenden Zeile — so bleiben JOIN und JOIN-Bedingung als zwei getrennte Strukturebenen erkennbar. Für die JOIN-Bedingungen gelten dieselben Regeln wie für die WHERE-Klausel.
1: SELECT
2: [...]
3: FROM
4: Tabelle1 T01
5: INNER JOIN Tabelle2 T02
6: ON
7: T01.[FK] = T02.[ID]
8: INNER JOIN Tabelle3 T03
9: ON
10: T02.[FK1] = T03.[FK1]
11: AND T02.[Feld2] = T03.[Feld2]
12: INNER JOIN Tabelle4 T04
13: ON
14: T03.[FK] = T04.[ID]
15: WHERE
16: [...]
GROUP BY, HAVING, ORDER BY
Für die verbleibenden Hauptelemente gelten dieselben Prinzipien wie für die SELECT-Feldliste und die WHERE-Klausel — kurz zusammengefasst:
GROUP BYenthält eine Liste von Gruppierungsausdrücken — bei einfachen Abfragen formatiert wie ein verkleinertesSELECT: pro Zeile ein Ausdruck mit vorangestelltem Komma, eingerückt nach Konvention.HAVINGist eine Bedingungs-Liste wieWHERE— Operanden spaltenartig ausgerichtet, gleichwertige Bedingungen gleich eingerückt. Der Unterschied zurWHERE-Klausel ist semantisch (post-GROUP BY-Filter), nicht typografisch.ORDER BYenthält eine Liste von Sortierausdrücken — formatiert analog zurGROUP BY-Klausel, mit optionalemASC/DESCje Ausdruck (in einer eigenen Spalte gehalten, wenn beide Sortier-Richtungen im Statement vorkommen).
1: SELECT
2: T01.[Region]
3: ,T01.[Year]
4: ,SUM(T01.[Sales]) AS [Total]
5: FROM
6: [dbo].[FactSales] T01
7: GROUP BY
8: T01.[Region]
9: ,T01.[Year]
10: HAVING
11: SUM(T01.[Sales]) >= 1000
12: AND COUNT(*) >= 10
13: ORDER BY
14: T01.[Region] ASC
15: ,T01.[Year] DESC
Auto-Formatter und „Formatieren ist Lernen“
Tools wie sqlfluff (Multi-Dialekt — T-SQL, Postgres, MySQL, BigQuery, …) und pgFormatter (Postgres-fokussiert) erzeugen die hier gezeigten Layouts automatisch und sind als Pre-Commit-Hook oder CI-Step nützlich. Ein Ersatz für das manuelle Formatieren sind sie nicht.
Der Akt des Einrückens, Alias-Ausrichtens und Klammer-Setzens zwingt den Entwickler, das Statement vollständig zu lesen und die Tabellen-Beziehungen mental zu modellieren. Auto-Formatter liefern das Layout — sie liefern nicht das mentale Modell, das beim Schreiben entsteht. Im Zeitalter von Copilot und Cursor ist das doppelt relevant: Generiertes SQL ohne Verständnis ist ein Risiko, denn es liefert technisch korrekte Abfragen, die die fachliche Frage trotzdem nicht beantworten.
Pragmatische Empfehlung: erst manuell formatieren, dann einen Formatter als finalen Konsistenz-Pass laufen lassen (z. B. sqlfluff fix).
Postgres-Brücke
Die Beispiele dieses Artikels stehen in T-SQL-Notation ([brackets], positionelle T01-Aliase). Die Layout-Regeln selbst sind engine-neutral — sie gelten 1:1 auch für Postgres. Es gibt nur eine Handvoll Stellen, an denen sich Postgres anders verhält, und keine davon ändert das Format-Pattern:
- Identifier-Quoting: Der SQL-Standard verwendet doppelte Anführungszeichen für delimited Identifier (
"name") — Postgres folgt dem. T-SQL nutzt typischerweise[brackets], versteht bei aktivemQUOTED_IDENTIFIERaber ebenfalls doppelte Anführungszeichen. Bei case-sensitiven Bezeichnern in Postgres wird das Quoting semantisch relevant (ein eigener Artikel zu Case-Sensitivity in SQL Server vs. Postgres ist geplant). DISTINCT ON: das Postgres-Idiom für „erste Zeile pro Gruppe“. Welche Zeile die erste ist, legt erst einORDER BYfest, das die Reihenfolge innerhalb der Gruppe eindeutig bestimmt — die linkenORDER BY-Ausdrücke müssen dabei dieDISTINCT ON-Ausdrücke sein. In T-SQL lässt es sich überROW_NUMBER() OVER (PARTITION BY … ORDER BY …)und einen Filter aufrn = 1emulieren. Die Formatierung folgt derSELECT-Feldliste.LATERAL: erlaubt einer Sub-Query in derFROM-Klausel, auf Spalten vorangehenderFROM-Elemente zuzugreifen. T-SQL nutzt dafürCROSS APPLY/OUTER APPLY. Formatiert wird einLATERAL-Join wie jeder andereJOIN.RETURNING: Postgres liefert beiINSERT/UPDATE/DELETEund seit Version 17 auch beiMERGEdie betroffenen Zeilen zurück. SQL Server bietet mitOUTPUTeine funktional verwandte Klausel mit eigener Syntax und eigenen Formen (OUTPUT INTO). Beide werden als eigene Klausel-Zeile mit Feldliste formatiert.- CTEs:
WITH …ist standardisiert und in beiden Engines grundsätzlich gleich aufgebaut, im Detail unterscheiden sich die Erweiterungen. Postgres hat die OptionenMATERIALIZED/NOT MATERIALIZED(siehe FAQ). JOIN-Einrückung,WHERE-Klammer-Pattern,ORDER BY-Listen: Für diese Layout-Muster gibt es keinen Engine-Unterschied.
Die Format-Disziplin trägt also auf beiden Engines. Zu den Postgres-Bezeichner-Spezifika ist ein eigener Folge-Artikel geplant.
Fazit
Die Hauptelemente eines SELECT-Statements gehören in separate Zeilen, ihre untergeordneten Elemente eine Einrückungsebene tiefer. Aus dieser Grundregel leiten sich alle Muster dieses Artikels ab: die Feldliste als vertikale Liste mit vorangestelltem Komma, die WHERE-Klausel mit spaltenartig ausgerichteten Operanden und gleich eingerückten gleichwertigen Bedingungen, die FROM-Klausel mit der Tabelle direkt hinter dem JOIN-Operator und dem ON-Schlüsselwort in einer eigenen Zeile.
Wer diese Muster konsequent anwendet, macht die Struktur eines Statements sichtbar, bevor der Inhalt gelesen ist: Die Klammer-Hierarchie einer verschachtelten WHERE-Klausel und die Beziehungen zwischen den Tabellen stehen bereits im Layout. Das Pattern ist engine-neutral und trägt in SQL Server wie in Postgres. Die Vokabel-Ebene dazu (Bezeichner, Delimiter, Kommata, Aliase) steht in Teil 1. Wichtiger als jede Einzelregel ist dabei, dass dieselbe Hierarchie im ganzen Projekt konsequent sichtbar bleibt — Konsequenz schlägt Reinheit.
FAQ
Nach den Regeln dieses Artikels: jede Klausel in eine eigene Zeile, untergeordnete Elemente eine Ebene tiefer. Jeder JOIN bekommt seine Tabelle direkt neben dem Operator und sein ON in der Folgezeile. In der WHERE-Klausel stehen gleichwertige Bedingungen untereinander, die Klammer-Hierarchie bestimmt die Einrückungstiefe. So bleibt auch ein Statement mit fünf Joins navigierbar.
Sobald die Unterabfrage das Statement unübersichtlich macht, mehrfach gebraucht wird oder einen eigenständigen logischen Schritt darstellt. CTEs lesen sich top-down statt verschachtelt und lassen sich in derselben Abfrage mehrfach referenzieren. SQL Server führt die definierende Abfrage bei mehrfacher Referenz allerdings unter Umständen erneut aus, denn eine CTE ist dort kein materialisiertes Zwischenergebnis. Zum Testen wird die äußere Abfrage vorübergehend durch ein SELECT * FROM cte_name ersetzt — standalone ausführbar ist eine CTE-Definition nicht. Einfache, nur einmal verwendete Sub-SELECTs dürfen bleiben.
JOIN-Operator immer explizit (INNER, LEFT, RIGHT, FULL) gekennzeichnet werden? Syntaktisch ist das INNER optional — ein nacktes JOIN bedeutet INNER JOIN. Dieser Style-Guide schreibt den JOIN-Typ trotzdem immer aus (INNER JOIN, LEFT JOIN, RIGHT JOIN, FULL JOIN): Der Default ist nicht jedem Leser geläufig, und beim Überfliegen ist der Unterschied zwischen JOIN und LEFT JOIN leicht zu übersehen.
Ja — die Layout-Regeln übertragen sich unverändert, siehe Abschnitt Postgres-Brücke. Die einzige praktische Anpassung ist das Identifier-Quoting ("…" statt […]). Die Layout-Regeln für SELECT-Feldliste, WHERE-Klausel, FROM-Klausel und JOIN-Einrückung sind engine-neutral.
Auto-Formatter liefern das Layout, aber nicht den Lerneffekt. Wer ein 200-Zeilen-Statement nur durch den Formatter laufen lässt, hat das Statement nicht gelesen. Wer es manuell strukturiert, baut die mentalen Modelle der Tabellen-Beziehungen auf — und entdeckt bei dieser Gelegenheit häufig logische Fehler. Pragmatischer Workflow: erst manuell, dann Formatter als Konsistenz-Feinschliff.
MATERIALIZED / NOT MATERIALIZED für CTEs in Postgres? Seit Version 12 faltet Postgres eine nicht-rekursive, nebenwirkungsfreie CTE standardmäßig in die übergeordnete Abfrage, wenn sie genau einmal referenziert wird — Predicate-Pushdown ist dann möglich. Bei mehrfacher Referenz faltet Postgres auch eine solche CTE standardmäßig nicht, sondern behandelt sie als eigenständige Berechnung. MATERIALIZED erzwingt diese separate Berechnung, NOT MATERIALIZED erlaubt das Falten auch bei mehrfacher Referenz. Für Performance-kritische Abfragen mit teuren CTEs lohnt der Blick in die Postgres-Doku zu WITH-Queries. SQL Server kennt keine entsprechende Syntax: Eine CTE ist dort kein eigenständig materialisiertes Objekt, sondern wird als Teil der Gesamtanweisung optimiert.
Teil 1 — Formatierung von SQL Statements. Dort geht es um die kleineren Bausteine: reguläre vs. delimited Identifier, das Komma vorne vs. hinten, systematische T01/T02-Aliase, qualifizierte Feldnamen. Teil 1 + Teil 2 zusammen ergeben einen vollständigen Style-Guide für SELECT-Statements.
Verwandte Artikel
Teil der Reihe:
- Formatierung von SQL Statements (Teil 1) — Bezeichner, Delimiter, Kommata, Aliase — die Vokabel-Ebene: reguläre vs. delimited Identifier, Komma-Position, systematische Aliase.
- Strukturierung und Formatierung von SQL Statements — der Cluster-Pfad — der Hub-Artikel mit dem Lesepfad durch alle Formatierungs-Themen dieses Blogs.
Vorgelagert:
- Die funktionale Ästhetik von SQL — das „Warum“ der SQL-Formatierung: Strukturierter Code lässt sich schneller lesen, reviewen und ändern.
Weiterführend:
- Komplexe SQL-Statements kommentieren — die Meta-Ebene: Inline- und Block-Kommentare, die die hier gezeigte Struktur dokumentieren, ohne sie zu zerstören.
- Editor-Optionen in SSMS — die Editor-Basis für dieses Layout: Tab-Weite, Leerzeichen statt Tabs, Blockauswahl.
- SQL-Konventionen // PL/pgSQL-Prozeduren, die man in zwei Jahren noch lesen kann — die Fortschreibung des Statement-Layouts für Postgres-Prozeduren.