Modern SQL formatting best practice is to uppercase all keywords (SELECT, FROM, JOIN, WHERE), keep table and column names lowercase with snake_case, indent nested clauses and subqueries by two or four spaces, put each JOIN and each WHERE condition on its own line, and run every query through an automated formatter so the style is enforced rather than argued about. Formatting is cosmetic — the SQL parser discards whitespace and case before execution — so it costs nothing at runtime and buys you readable code, cleaner diffs, and faster review.
That's the summary an AI Overview would give you. Here's what a summary can't show you: the choices where reasonable engineers actually disagree — leading vs. trailing commas, tabs vs. spaces, AS or no AS — and the trade-off behind each one. Below is a decision table for those arguments, a before/after diagram of what "formatted" actually means, and a live formatter you can paste your own query into without leaving the page.
The style decisions teams actually argue about
Most of SQL formatting is settled: keywords up, names down, indent the nesting. The friction is in a handful of choices where both options are defensible. Here's the honest trade-off on each, with a recommendation you can adopt as-is.
| Decision | Option A | Option B | Trade-off | Recommended default |
|---|---|---|---|---|
| Keyword case | SELECT (uppercase) | select (lowercase) | Uppercase separates structure from data without relying on a color scheme; lowercase is less shouty and leans on syntax highlighting | Uppercase — survives plain-text contexts (logs, tickets, email) |
| Identifier case | order_total (snake_case) | orderTotal (camelCase) | snake_case is case-insensitive-safe across dialects; camelCase breaks on case-folding databases | snake_case — portable and dialect-safe |
| Commas | Leading (, col) | Trailing (col,) | Leading = one-line diffs and easy-to-spot missing commas; trailing = reads naturally, matches other languages | Leading for big/volatile SELECT lists, trailing elsewhere |
| Indentation | Spaces | Tabs | Spaces render consistently everywhere SQL gets pasted; tabs respect personal width but render unpredictably | Spaces (2 or 4) — travels across tools |
| JOIN layout | Each JOIN on its own line | JOINs inline | Own-line makes table count and join type obvious at a glance | Each JOIN on its own line |
| WHERE operators | AND at line start | AND at line end | Leading operators make the condition list read as a vertical checklist and diff cleanly | Leading AND/OR |
| Column aliases | total AS order_total | total order_total | Explicit AS prevents the missing-comma-becomes-alias bug | Use AS for columns |
| Enforcement | Formatter in CI | Style doc only | A documented style nobody runs drifts within weeks; a formatter makes it non-negotiable | Automate it — a linter/formatter, not a wiki page |
If you only take one row from this table, take the last one. Every other decision stops mattering the moment the style is applied automatically on save or in a pre-commit hook, because nobody has to think about it or police it in review again.
What "formatted" actually means
Here is the same query as a wall of text and as properly formatted SQL. The parser treats them identically — the difference is entirely for the human reading the diff six months from now.
Format your own query right now
Paste a query below to apply these conventions automatically across MySQL, PostgreSQL, SQL Server, Oracle, SQLite, and more. It runs entirely in your browser — nothing is sent to a server.
A worked reference style
If you want a concrete target to standardize on, this is a clean, widely-compatible baseline that satisfies every recommended default in the table above:
SELECT
o.id AS order_id
, c.name AS customer_name
, o.total AS order_total
, o.created_at AS placed_at
FROM orders AS o
JOIN customers AS c
ON o.customer_id = c.id
WHERE o.total > 100
AND o.status = 'paid'
ORDER BY o.created_at DESC
LIMIT 50;
Notice the deliberate choices: uppercase keywords, snake_case identifiers, leading commas aligned under the first column, AS on every column alias, each JOIN and its ON on their own lines, and AND at the start of its line. The alignment of the AS keywords is optional — it looks tidy but creates larger diffs when a column name changes width, so many teams skip it. That single caveat is the kind of thing a style guide should decide once, for everyone.
Why formatting is a security and review concern, not just aesthetics
Consistent formatting is not decoration. Readable SQL is auditable SQL. When every query in your codebase follows the same shape, a reviewer can scan for the patterns that matter — an unparameterized value concatenated into a WHERE clause (the classic SQL injection vector), a missing WHERE on an UPDATE or DELETE, an accidental cross join from a forgotten ON. Those defects hide easily inside a one-line query and jump out of a formatted one. A formatter enforced in CI also means the diff for a logic change shows only the logic change, not a reformatting war, which keeps review focused on behavior instead of whitespace.
Common formatting mistakes to avoid
- Mixing keyword cases within a file —
SELECTon one line andselectthree lines down signals nobody is running a formatter. Pick one, automate it. - Deep-nesting subqueries instead of using CTEs — a
WITHclause with named steps reads top-to-bottom; a triple-nested subquery reads inside-out. Formatting can't rescue a structure that fights the reader. - Aligning everything by hand — hand-aligned columns and keywords look great until the next edit knocks them out of alignment and you're maintaining whitespace by hand. Let the tool do it, or don't do it.
- Relying on a style doc nobody runs — a wiki page describing your SQL style drifts out of reality within weeks. The only style that sticks is the one a machine applies.
- Formatting to hide complexity — pretty-printing a 400-line query doesn't make it maintainable. If formatting is the only thing making a query readable, the query itself needs refactoring into CTEs or views.
Key takeaways
- The settled rules — uppercase keywords, lowercase snake_case identifiers, indented nesting, one clause per line — are non-negotiable baseline and every major style guide agrees on them.
- The genuinely debatable choices (leading vs. trailing commas, tabs vs. spaces,
ASor not) all have defensible answers; the table above gives you a recommended default for each. - Formatting never affects execution — same plan, same speed, same results — so there is no runtime reason to skip it.
- The one decision that makes all the others irrelevant is automation: enforce the style with a formatter in a pre-commit hook or CI, not with a document.
- Readable SQL is reviewable SQL, and reviewable SQL is where injection bugs and missing
WHEREclauses get caught before they ship.