SQL Formatter
Most of what looks like a logic bug is visible once the clauses line up
A query copied out of an ORM log or a bug report usually arrives as one long line. At that width you cannot see which ON clause belongs to which JOIN, whether a filter ended up in a join condition instead of the WHERE, or how deep a subquery goes. Indenting changes nothing about the SQL — it changes what you can read. The classic case: a condition written into the ON clause of a LEFT JOIN, where it keeps unmatched rows that the same condition in the WHERE would have removed. On an INNER JOIN the two placements are equivalent, which is exactly why the mistake survives review.
It formats. It does not validate.
Nothing here parses your schema, checks that the tables exist, or judges whether the syntax is legal in your engine. A query with a misspelled column name will format perfectly. There is no database connection and nothing is executed — only the database you intend to run against can tell you the query is correct.
The query stays in the browser
Formatting happens in the page. Real queries are not neutral text: they carry table and column names, and often literal values such as account IDs, email addresses or the date range from a production incident. None of that is uploaded, stored or logged. If you want proof rather than a promise, watch the browser network panel while you press Format.
Conventions worth settling before formatted SQL goes into a commit
- Uppercase keywords. Keywords are case-insensitive, so this is for reading only — it separates
ORDERthe keyword from anorder_datecolumn at a glance. Identifiers are a different matter: unquoted names are folded to lower case by PostgreSQL and to upper case by Oracle, so leave table and column names exactly as written. - Leading commas. A comma at the start of each line in the
SELECTlist means adding or removing a column at the end of the list touches one line in the diff instead of two, and a missing comma is visible down the left edge rather than hidden at a line end. The first column is the exception — it still moves. - One clause per line.
FROM, eachJOIN,WHERE,GROUP BYandORDER BYstarting at the same indent gives you the outline of the query at a glance.
The one-line direction is for the opposite job: putting a query back into a code string, a JSON field, a config value or a single log line. Check for -- comments first — collapsed onto one line, everything after a -- is commented out to the end. /* ... */ block comments survive.
Share this tool with friends
Free to use, no sign-up, works on any phone.
Frequently Asked Questions
No. Formatting runs in your browser, so the query text never leaves the page: nothing is uploaded, stored or logged. That matters more for SQL than for most pasted text, because a real query carries your table and column names and often literal values lifted straight from an incident, such as account IDs or email addresses. If you want to check rather than take our word for it, open the browser network panel and press Format — no request goes out.
No. It is a formatter, not a validator or a linter: it rearranges whitespace and line breaks and makes no judgement about whether the query is legal. A misspelled column, a table that does not exist, or syntax your engine rejects will all format without complaint. Badly broken input tends to come out oddly indented, which is a hint but not a verdict. Nothing is executed here, so only your database can confirm the query runs.
It works on layout, not on dialect grammar. It does not check whether your syntax is valid in PostgreSQL, MySQL, SQL Server, Oracle or SQLite, and it will not translate engine-specific syntax from one dialect into another. If your query leans on vendor extensions — optimiser hints, dollar-quoted blocks, square-bracket identifiers — read the output before you commit it rather than assuming the layout left them untouched.
Put each clause on its own line at a consistent indent, with every join condition sitting next to the join it belongs to. Many wrong-result bugs are structural rather than arithmetic: a filter written into the ON clause of a LEFT JOIN, where it keeps unmatched rows that the same filter in the WHERE would have removed; a join added one level too early; a subquery correlated to the wrong outer table. Those are near-invisible on one line and hard to miss once indented.
Purely for reading. Keywords are case-insensitive in every mainstream engine, so SELECT and select run identically; capitalising them separates the language from your identifiers, which helps when a column is called value, count or status. Identifier casing is not cosmetic in the same way: PostgreSQL folds unquoted names to lower case, Oracle folds them to upper case, and MySQL table-name matching depends on the filesystem and configuration. Leave table and column names exactly as you typed them.
Not in itself — whitespace mainly separates tokens, so the parser sees the same statement. Three things do care. Quoted string literals and quoted identifiers, where spaces and newlines are part of the value. A -- comment, which runs to the end of the line, so collapsing a query onto one line comments out everything after it. And MySQL, which by default expects no space between a built-in function name and its opening parenthesis. Block comments survive the collapse.