Guide
How to format SQL for readability
Learn why consistent SQL formatting speeds up review and debugging, the conventions that matter, and how to apply them. A SQL formatter is built in.
SQL is whitespace-insensitive: the engine does not care whether your query is one long line or forty short ones. That freedom is exactly why formatting matters for people. A consistently formatted query is faster to review, easier to debug, and produces smaller, clearer diffs. The tool above applies these conventions in one pass.
Why formatting pays off
A query you wrote yourself five minutes ago is readable in any shape. The same query in a pull request, a bug report, or a six-month-old migration is not. Formatting helps at the moments that cost the most time:
- Review. A reviewer can verify that the right columns are selected and the right tables are joined only if those are visible at a glance.
- Debugging. When a result is wrong, you scan the
WHEREandJOINclauses. Aligned, one-condition-per-line formatting makes a missing or extra predicate jump out. - Diffs. With one column per line, adding a column changes one line in version control instead of rewriting a long line that hides the real change.
Because formatting never affects how the query executes, there is no runtime cost to making it readable.
The conventions that matter
A few rules cover most of what makes SQL readable:
- Keyword case. Uppercase the SQL keywords (
SELECT,FROM,WHERE,JOIN,GROUP BY) so they contrast with lowercase identifiers. Pick one casing and apply it everywhere. - Clause on its own line. Start each major clause on a new line, left-aligned, so the skeleton of the query reads top to bottom.
- One column per line. In the
SELECTlist, give each column its own line. The same applies to longGROUP BYandORDER BYlists. - JOINs aligned. Put each
JOINon its own line underFROM, with itsONcondition close by. - Indent subqueries one level so nesting is visible.
Before and after
The difference is stark on even a small query:
-- before
select u.id, u.name, o.total, o.created_at from users u join orders o on o.user_id = u.id where o.total > 100 and u.active = 1 order by o.created_at desc;
-- after
SELECT
u.id,
u.name,
o.total,
o.created_at
FROM users u
JOIN orders o ON o.user_id = u.id
WHERE o.total > 100
AND u.active = 1
ORDER BY o.created_at DESC;
Both run identically. The second version lets a reviewer confirm in seconds which columns return, which tables join and on what, and which conditions filter the rows, without parsing one dense line.
Dialect notes
The core clauses (SELECT, FROM, JOIN, WHERE, GROUP BY, HAVING, ORDER BY) format the
same across every major database. Where dialects diverge is the surrounding syntax:
- Identifier quoting. MySQL uses backticks, PostgreSQL and the standard use double quotes, and SQL Server uses square brackets. A formatter should leave these untouched.
- Row limiting. MySQL and PostgreSQL use
LIMIT; SQL Server usesTOPorOFFSET ... FETCH. - String and date functions. Names and arguments differ between engines, so a formatter focuses on layout rather than rewriting these.
Choosing the matching dialect in the tool above produces output that respects your engine's quoting and limiting syntax. Once a team agrees on a formatting style and applies it on every commit, SQL stops being a wall of text and becomes something you can read like the rest of the codebase.