glunty

Blog   /   guides   /  

How to format SQL for readability

How to format SQL for readability: keyword case, one column per line, indentation for joins and subqueries, plus dialect notes and a before/after example.

A SQL query that works but reads badly is one nobody wants to touch. It runs, so it stays, and every change gets grafted onto a wall of run-on clauses no reviewer fully parses. Formatting does not make a query correct, but it makes correctness visible, which is what you need when a bug hides in a five-table join.

This guide covers why formatting matters, the conventions teams converge on, how they shift across dialects, and a worked example. Throughout: formatting changes how a query looks, never what it does.

Why formatting matters for review and diffs

Two forces make formatting more than cosmetic. The first is review. A reviewer has to reconstruct a query’s shape in their head: which tables, which joins, which filters. When every clause sits on its own line, that shape is legible at a glance. When it is one paragraph, the reviewer skims and approves blind or reformats it mentally first.

The second force is version control diffs. If a query keeps each column and clause on its own line, adding one column produces a one-line diff, so reviewers see exactly what changed. Pack the whole SELECT onto one line and that same edit rewrites the entire line: the diff says “this long line changed” and the real change hides inside it. Line-oriented formatting turns git blame and review into precise tools instead of guesswork.

Conventions most teams agree on

There is no single official SQL style, but a few conventions show up everywhere because they earn their keep.

Keywords starting new lines. Put the major clause keywords (SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY) at the start of a new line. This gives the query a visible skeleton, so your eye finds the WHERE clause instantly because it is anchored to the left margin rather than buried mid-line.

One column per line for long SELECTs. A SELECT with two or three columns can stay on one line. Once it grows past that, give each column its own line. Leading or trailing commas both work; pick one and stay consistent. This keeps additions, removals, and reordering clean.

Consistent keyword case. Uppercase keywords against lowercase identifiers is the most common convention because it separates the language from your data at a glance. All-lowercase is fine too. What matters is choosing one and applying it everywhere; mixing SELECT and select in one file is the readability killer, not the case itself.

Indentation for joins and subqueries. Indent join conditions under their JOIN, and indent a subquery’s body one level deeper than the query that contains it. Nesting depth then maps to indentation depth, so you see how deep you are without counting parentheses.

Applying these by hand is tedious, which is what a tool is for. The SQL formatter applies all of them in one pass, in your browser, so you paste messy SQL and get a consistent result.

Dialect differences to keep in mind

SQL is a family of dialects, not one language, and formatting brushes up against real syntax differences. Postgres, MySQL, SQL Server, SQLite, and BigQuery each have their own quoting rules: standard SQL and Postgres use double quotes for identifiers, MySQL uses backticks, and SQL Server accepts square brackets. A formatter must respect the dialect or it will mangle a quoted identifier into a syntax error.

Keyword sets differ too: LIMIT versus TOP, clauses like QUALIFY in some analytics dialects, and dialect-specific functions all mean a formatter must know which dialect it reads to case keywords correctly and not treat a function name as an identifier. So tell your tool which dialect you use, and keep one style within a codebase rather than letting Postgres and MySQL files drift apart.

Formatting never changes what a query does

This guarantee makes reformatting risk-free. Whitespace, line breaks, indentation, and keyword case are invisible to the SQL engine. SELECT id, name FROM users and the same query spread across six indented lines produce byte-for-byte identical results and identical query plans. The one thing to watch is inside string literals and quoted identifiers, where characters are data; a good formatter leaves those alone. So reformatting working queries is safe any time; you never re-test behavior afterward, only re-read for clarity.

Before and after

Here is a messy query as it often arrives from an app log:

select u.id,u.name,o.total from users u join orders o on o.user_id=u.id where u.active=1 and o.total>100 order by o.total desc

It works, but the join condition, filters, and columns all blur together. Formatted:

SELECT
    u.id,
    u.name,
    o.total
FROM users AS u
JOIN orders AS o
    ON o.user_id = u.id
WHERE u.active = 1
    AND o.total > 100
ORDER BY o.total DESC;

Same query, same result, but now the join condition is obvious, the filters stack under WHERE, and adding a fourth column would be a one-line diff. If you inherit a query like this, the AI SQL explainer walks through each clause in plain English, which pairs well with formatting: clean it up, then read it.

Closing

Formatting SQL is low effort and high return: it costs seconds and pays off every time someone reviews, diffs, or debugs the query later. Pick your conventions, apply them consistently, and remember that none of it changes the result. The query does what it did before; now you can see what that is.

Embedded tool from glunty.com