SQL Formatter

Reformat a SQL query in your browser for Postgres, MySQL, SQLite, T-SQL or generic SQL, with an indent width from 2 to 8 spaces. Nothing is uploaded.

🌐 Español

🔒 Private by design: your text is processed locally in your browser and never uploaded to any server.

What a formatter is for, and what it is not for

A SQL formatter solves one problem: a query that arrived as a single unreadable line, usually copied out of an application log, an ORM’s debug output or a colleague’s message. Reformatting it puts each clause on its own line and indents the parts that nest, which is the difference between a query you can reason about and a wall of text you skim.

What it does not do is check the query. This distinction gets blurred by tools that call themselves validators, so it is worth stating plainly here. The grammar behind this page is intentionally permissive, and it will happily format text that no database would run. Its no-complaints response tells you the punctuation balances, and nothing more than that.

Formatting a query

  1. Paste the query, or a whole script of several statements, into the input box.
  2. Choose a SQL dialect. Leave it on generic unless the query uses syntax specific to one database.
  3. Set Indent size (spaces) between 2 and 8.
  4. Run it and read the formatted result.
  5. Copy the output, or download it as a .sql file.

Dialects, and why generic is the default

The dialect setting picks which grammar parses your query. Five are available: a generic dialect-agnostic grammar, PostgreSQL, MySQL, SQLite and T-SQL for SQL Server.

Generic is the default on purpose. The most common situation for anyone reaching for an online formatter is holding a query whose origin they did not choose and do not necessarily know, and for ordinary selects, joins, subqueries and common table expressions the generic grammar handles it correctly. Switching dialect is worth doing when the query contains something that only one database supports, where a dialect-aware grammar recognises the construct rather than tripping over it.

If a stray or unrecognised value ever reaches the dialect setting it resolves to generic rather than being passed through to the library, which would otherwise raise a configuration error instead of a formatting one.

Indent width in practice

Two spaces is the default and it suits most queries. Four is worth choosing when the query nests several levels deep, because at two spaces a subquery inside a subquery inside a case expression becomes hard to trace by eye. Eight is available and is mostly useful when the result has to survive being pasted somewhere that collapses or re-tabs whitespace.

The field is clamped rather than validated: a value below two becomes two, a value above eight becomes eight, and a fractional value is rounded. So there is no way to produce an output with broken indentation by mistyping the field.

When it refuses, and what the refusal tells you

A failed parse does not throw the query away. The result box shows a short line naming the token that stopped the parser and the line and column it reached, which in practice points almost straight at the missing bracket or the stray character.

The most common cause by far is a query copied out of a log where a quote or a parenthesis got truncated. The second most common is a template placeholder that was never substituted, leaving something like a bare question mark or a named parameter that the grammar cannot place. Comparing the broken copy against a known good one with Diff Text is often faster than reading it again.

For the other two structured formats that arrive equally mangled, JSON Formatter and XML Formatter do the same job with real validation behind them, since both of those grammars are strict in a way SQL’s is not. YAML to JSON covers configuration files, and CSV to SQL goes the other way by turning tabular data into insert statements. The rest are on the dev tools hub.

See it in action

Screenshot of the SQL Formatter tool with the sample input “select t.slug, t.category, count(*) as hits from…”, SQL dialect set to Generic SQL (default), Indent size (spaces) set to 2
SQL Formatter mid-process: the sample input “select t.slug, t.category, count(*) as hits from…”, SQL dialect set to Generic SQL (default), Indent size (spaces) set to 2.
Screenshot of the SQL Formatter result screen showing the generated output “select t.slug, t.category, count(*) as hits from…”
The finished result: the generated output “select t.slug, t.category, count(*) as hits from…”. The download link is a local blob URL — the file never leaves your device.

Frequently asked questions

Will this tell me whether my query is valid?

Only partly, and it is worth being precise about the limit. The formatter is built on a deliberately lenient free-form SQL grammar, so it reliably catches structurally broken input such as unbalanced parentheses or stray invalid punctuation, but it is not a semantic validator. Plain English with no odd punctuation formats without complaint, and so does a query with a keyword repeated three times in a row. Formatting successfully means the text parses as a shape, not that a database would accept it.

What happens when it cannot parse the query?

The result box gets a short failure notice instead of formatted SQL, naming the token and the line and column where the parser gave up. That is genuinely useful for finding an unclosed bracket. The underlying library actually produces a message that can run to thousands of lines listing every grammar production it expected at that point, so only the first line of it is kept. The rest is a grammar dump with no value to a human.

Does it change my keywords to uppercase?

No. The formatter rearranges whitespace and line structure only. If you write select in lowercase it stays lowercase, and if you write SELECT it stays uppercase. There is no case option here, so a mixed-case query keeps its mixture. If you want consistent casing, apply it before formatting.

What difference does picking a dialect make?

It selects the grammar used to parse the query, which affects how dialect-specific syntax is recognised and laid out. Generic SQL is the default because it is the safe choice when you neither know nor care which database a query came from, and it handles ordinary joins, subqueries and clauses perfectly well. Reach for a specific dialect when your query uses something only that database has. An unrecognised dialect value falls back to generic rather than failing.

Why does the indent only go down to 2 spaces?

Because a one space SQL indent is not a real preference. Flat JSON can arguably justify one, since its nesting is shallow and machine read as often as not, but SQL nesting exists to make clause structure visible to a person and one space defeats the purpose. The field accepts 2 through 8, rounds a fractional value, and clamps anything outside that range to the nearest end.

Is my query sent anywhere?

No. The formatting library is bundled with the page and runs inside your browser tab, so the query never leaves your device. That matters more for SQL than for most text, because a real query usually carries table names, column names and sometimes literal values from a production schema, all of which is information most teams would not paste into an unknown web service.

Can it format more than one statement at a time?

Yes. A script containing several statements separated by semicolons is formatted as a whole, with each statement laid out in turn. There is no per-statement limit and no length limit beyond what your browser can hold in memory, so a long migration file is fine.

Related tools