Developer FIELD NOTES · 3 MIN READ
Formatting SQL: Why Pretty Queries Catch More Bugs
How SQL formatting works: clause line breaks, indentation conventions, and why readable queries are easier to debug.
A five-line SQL query is easy to read. A fifty-line query with four joins, two subqueries, and a CASE expression is where bugs hide — and most of them hide behind a comma or a missing condition that proper formatting would have made visible. Formatting SQL is not cosmetics; it is debugging.
Why unformatted SQL hides bugs
SQL is written left to right, but humans review it top to bottom. An unformatted one-liner forces the reader to scan a 400-character string looking for the one WHERE clause that runs before the JOIN it was supposed to filter. When every major clause starts its own line, the query's structure becomes the indentation — you can see at a glance what gets selected, from where, filtered by what, in which order.
Missing commas are the classic example. In a long SELECT list written as one line, a dropped comma turns two columns into one alias-mangled expression, and the database will happily return nonsense. When each column sits on its own line, the missing comma is a visual gap you cannot miss.
What a formatter actually does
SQL formatters are heuristic, not parsers — and that is fine, because the conventions they enforce are simple. A typical pass does three things:
- Breaks major clauses onto their own lines —
SELECT,FROM,WHERE,GROUP BY,ORDER BY,LIMIT, and everyJOIN/ONpair. - Indents continuation lines — usually 2 or 4 spaces, so column lists and conditions visually belong to the clause above them.
- Normalizes commas and spacing — one space after each comma, no stray double spaces, and a trailing semicolon.
A worked example
Take this perfectly legal but perfectly unreadable query:
select name, age, city from users where age > 30 and city = "Chicago" inner join orders on users.id = orders.user_id order by name limit 10
Run it through a formatter and you get:
select name, age, city
FROM users
WHERE age > 30 and city = "Chicago"
INNER
JOIN orders
ON users.id = orders.user_id
ORDER BY name
LIMIT 10;
Every clause boundary is now a line boundary. Notice two honest quirks in this output: keyword case is preserved rather than rewritten (the first line's select stayed lowercase — the formatter breaks lines, it does not enforce case), and the INNER JOIN split onto two lines because "INNER" ends the previous line. Heuristic formatters have rough edges on complex joins — which is exactly why you read the output before shipping it.
The two house styles: leading vs trailing keywords
Teams argue endlessly about which keyword goes at the start of a line:
SELECT name
FROM users
WHERE age > 30
AND city = 'Chicago'
versus the trailing style:
SELECT
name
FROM users
WHERE
age > 30
AND city = 'Chicago'
The leading-keyword style (first example) is the easier one to diff and to scan — every clause starts at the left margin, and AND/OR conditions line up vertically so adding a condition is a one-line change. Whatever your team picks, the formatter's job is to make it consistent; the specific style matters far less than never mixing them.
When not to bother
Single-clause queries — SELECT * FROM users; — gain nothing from being split across five lines. A good rule of thumb: format anything with a JOIN, more than three columns, or any subquery. One-liners stay one-liners. Formatting is a tool for humans reading the query later, and sometimes that human is future you, five minutes from now, hunting a typo.
Try it yourself
Paste a messy query into the SQL Formatter and watch the clause structure appear. If your data is coming from or going to other formats, the CSV to JSON Converter and the JSON to YAML Converter apply the same idea — normalize the shape first, read it second — to non-SQL data.