SQL formatieren
Der SQL-Formatter rückt eine Abfrage in Ihrem Browser neu ein. Er tokenisiert das SQL zuerst, statt Schlüsselwörter mit einem regulären Ausdruck zu suchen – genau das unterscheidet einen Formatter, der funktioniert, von einem, der am ersten String-Literal scheitert, das das Wort FROM enthält.
Wie funktioniert SQL formatieren?
An einem SQL-Formatter wird gemessen, was er mit der Abfrage anstellt, mit der er nicht gerechnet hat. Vier Dinge trennen einen, über den man gefahrlos eine ganze Codebasis laufen lässt, von einem, der still und leise eine Migration korrumpiert.
Tokenisierung statt Musterabgleich
Die naheliegende Implementierung findet Schlüsselwörter mit einem regulären Ausdruck und fügt Zeilenumbrüche ein. Das funktioniert, bis eine Abfrage 'FROM cache' als String-Literal enthält oder einen Kommentar mit Apostroph – und dann liefert sie etwas, das sich nicht mehr parsen lässt. Hier wird die Abfrage zuerst tokenisiert – Strings, Bezeichner, Kommentare, Zahlen, Operatoren und Schlüsselwörter sind getrennte Dinge – und nur Schlüsselwort-Tokens beeinflussen das Layout. Die Beispielabfrage oben enthält genau deshalb ein String-Literal mit dem Wort FROM.
Bezeichner in Anführungszeichen werden nie umgeschrieben
"User" und User sind auf einer Datenbank mit Groß- und Kleinschreibung unterschiedliche Objekte. Ein Formatter, der die Anführungszeichen „aufhübscht“, hat verändert, welche Tabelle die Abfrage liest. Die Zitierweise unterscheidet sich außerdem je nach Dialekt – das Backtick bei MySQL, eckige Klammern bei T-SQL, das doppelte Anführungszeichen im Standard – deshalb geht es bei der Dialektauswahl um korrektes Parsen, nicht um den Ausgabestil.
Dialektspezifische Regeln für Strings
Der Standardweg, ein Anführungszeichen innerhalb eines Strings zu escapen, ist es zu verdoppeln; MySQL akzeptiert zusätzlich einen Backslash. Postgres hat Dollar-quoted Strings, deren Trennzeichen der Autor selbst wählt – $func$ … $func$ – die genau deshalb existieren, damit ein Funktionskörper alles enthalten kann. Ein Tokenizer, der das nicht kennt, beendet einen String zu früh, und alles danach wird falsch eingeordnet.
Kommentare behalten ihre Position
Ein Kommentar in einer eigenen Zeile bleibt in einer eigenen Zeile; ein Kommentar am Zeilenende bleibt am Zeilenende. Blockkommentare verschachteln im SQL-Standard, anders als in C, daher ist /* a /* b */ c */ ein einzelner Kommentar und kein Syntaxfehler. Beim Minifizieren wird ein -- Kommentar in einen Blockkommentar umgewandelt, weil ein Zeilenkommentar auf einer einzigen Zeile den Rest der Abfrage auskommentieren würde – ein kleines Detail, das aus einer minifizierten Abfrage eine kaputte macht.
Das Layout der Ausgabe
Klauseln beginnen eine Zeile; Joins beginnen eine Zeile; jede Spalte bekommt eine eigene Zeile; boolesche Verknüpfungen in einem WHERE beginnen eine Fortsetzungszeile, aber nur auf der obersten Ebene – ein AND innerhalb von (y = 2 AND z = 3) ist Teil eines Ausdrucks und bleibt, wo es ist. Führende Kommas sind verfügbar, weil sie eine Spaltenliste in einem Diff leichter umordnen – ein echtes Argument, auch wenn es zunächst seltsam aussieht.
Eingabe
select a,b from t where x=1 and y=2
Formatiert
SELECT a, b FROM t WHERE x = 1 AND y = 2
Welche Optionen und Sonderfälle unterstützt SQL formatieren?
| Parameter | Typ | Standard | Verhalten & Sonderfälle |
|---|---|---|---|
| Dialekt | standard / postgres / mysql / tsql | postgres | Beeinflusst das Parsen, nicht den Stil: welche Zeichen einen Bezeichner quoten, wie eine Zeichenfolge ein Anführungszeichen maskiert und ob Dollar-Quoting und #-Kommentare existieren. |
| Schlüsselwörter in Großbuchstaben | Boolesch | ein | Nur Schlüsselwörter. Bezeichner, Zeichenfolgen und Kommentare behalten ihre ursprüngliche Schreibung, denn auf manchen Datenbanken ändert eine geänderte Schreibweise eines Bezeichners, welches Objekt er benennt. |
| Spalte pro Zeile | Boolesch | ein | Eine ausgewählte Spalte pro Zeile. So zeigt ein Diff, welche Spalte sich geändert hat, statt nur, dass die SELECT-Zeile geändert wurde. |
| Vorangestellte Kommas | Boolesch | aus | Das Komma vor der Spalte statt danach. Spaltet die Gemüter, und Umstellen ist wirklich einfacher: Fügt man hinten eine Spalte an, bleibt die vorherige Zeile unberührt. |
| String-Literale | unverändert | Byte für Byte | Einschließlich der Leerraumzeichen darin. Eine Zeichenfolge ist Daten, und Daten umzuformatieren ist keine Formatierung. |
| Bezeichner in Anführungszeichen | unverändert | — | "User" ist auf einer Datenbank mit Groß-/Kleinschreibung nicht User. Die Anführungszeichen werden nie hinzugefügt oder entfernt. |
| Blockkommentare | verschachtelt | — | Standard-SQL schachtelt sie, anders als C. /* a /* b */ c */ ist ein Kommentar, und ein Tokenizer, der am ersten */ stoppt, liest den Rest der Abfrage falsch. |
| Minifizieren | eine Zeile | — | Zieht den Leerraum zusammen und wandelt Zeilenkommentare in Blockkommentare um, denn ein -- Kommentar auf einer Zeile kommentiert alles dahinter aus. |
Häufig gestellte Fragen
Warum enthält die Beispielabfrage 'FROM cache'?
Um den Unterschied zwischen einem tokenisierenden und einem Regex-basierten Formatter zu zeigen. Ein Formatter, der Schlüsselwörter per Muster findet, sieht das FROM innerhalb dieses String-Literals, fügt mitten darin einen Zeilenumbruch ein und erzeugt eine Abfrage, die sich nicht mehr parsen lässt. Wer zuerst tokenisiert, für den ist ein String ein String, egal was er enthält.
Ändert er meine Tabellen- oder Spaltennamen?
Nein. Nur Schlüsselwort-Tokens werden in ihrer Groß- und Kleinschreibung angepasst, und Bezeichner in Anführungszeichen werden Byte für Byte durchgereicht, einschließlich ihrer Anführungszeichen. Das ist wichtiger, als es klingt: Auf Postgres bezeichnen "User" und User verschiedene Tabellen – ein Formatter, der Anführungszeichen entfernt, ändert also die Bedeutung der Abfrage und nicht nur ihr Aussehen.
Welchen Dialekt soll ich wählen?
Den, der Ihrer Datenbank tatsächlich entspricht, denn die Einstellung betrifft das Parsen, nicht den Stil. MySQL verwendet Backticks für Bezeichner und akzeptiert Backslash-Escapes in Strings; T-SQL verwendet eckige Klammern; Postgres hat Dollar-quoted Strings. Die falsche Wahl bedeutet, dass ein String oder Bezeichner an der falschen Stelle endet und alles danach falsch eingeordnet wird.
Führende Kommas – warum sollte jemand das wollen?
Weil das Hinzufügen oder Entfernen der letzten Spalte einer Liste nur eine Zeile berührt statt zwei. Mit nachgestellten Kommas bedeutet das Anfügen einer Spalte, die vorherige Zeile bearbeiten zu müssen, um dort ein Komma zu ergänzen – der Diff zeigt dann zwei geänderte Zeilen, und ein Reviewer muss beide prüfen. Es sieht etwa einen Tag lang seltsam aus, und dann ist es egal.
Wird eine Abfrage durch Minifizieren schneller?
Nein. Die Datenbank parst die Abfrage, bevor sie sie plant, und Whitespace wird in diesem Stadium verworfen; eine minifizierte und eine formatierte Abfrage erzeugen identische Pläne. Minifizieren dient dazu, eine Abfrage auf eine Zeile zu bringen – in ein Log, eine Konfigurationsdatei, einen Shell-Befehl – nicht der Performance.
Wird meine Abfrage hochgeladen?
Nein. Tokenisierung und Formatierung laufen in dem Tab, den Sie bereits geöffnet haben. Das ist hier relevant, weil Abfragen Dinge enthalten, die man nirgendwo einfügen würde: Tabellen- und Spaltennamen, die ein Geschäft beschreiben, und oft Literalwerte, die echte Kundendaten sind.