SQL Formatter
Pretty-print and indent messy SQL: clause-per-line layout, aligned joins, and optional keyword uppercasing. String literals and comments are preserved. Runs in your browser.
Formatted
SELECT u.id, u.name, COUNT(o.id) AS orders FROM users u LEFT JOIN orders o ON o.user_id = u.id WHERE u.status = 'active' AND u.created_at > '2024-01-01' GROUP BY u.id, u.name HAVING COUNT(o.id) > 2 ORDER BY orders DESC LIMIT 20;
String literals, quoted identifiers, and comments are preserved exactly — only whitespace and keyword case change, so the statement stays semantically identical.
About this tool
A one-line SQL query copied from a log or an ORM is hard to read and harder to review. This formatter parses the statement and lays it out the conventional way: each major clause (SELECT, FROM, WHERE, GROUP BY, ORDER BY, and so on) starts a new line at the base indent, joins and their ON conditions are grouped, AND/OR conditions are indented under WHERE, and keywords can be uppercased so they stand out from identifiers. Crucially, it works by tokenizing the SQL first — string literals, quoted identifiers, and both line and block comments are pulled out and put back untouched — so reformatting can never alter what the query means. The transformation only changes whitespace and keyword case; the exact tokens, in the exact order, are preserved. It runs entirely in your browser, so even queries containing sensitive table or column names never leave your machine. It is a readability formatter, not a linter or a full SQL parser, so it favors clean layout over dialect-specific validation.
How to use it
- Paste a SQL statement (any dialect).
- Toggle 'Uppercase keywords' to match your house style.
- Read the formatted, clause-per-line output.
- Copy it back into your editor or pull request.
Frequently asked questions
- Will formatting change what my query does?
- No. The formatter only adjusts whitespace and the case of recognized keywords. String literals, quoted identifiers, and comments are extracted before formatting and restored verbatim, so the sequence of tokens — and therefore the meaning — is identical to the input.
- Does it work with my SQL dialect?
- Largely, yes. It recognizes the standard clause keywords shared across PostgreSQL, MySQL, SQL Server, SQLite, and others, and it treats anything it does not recognize as an identifier, so dialect-specific functions and syntax pass through intact. It is a layout tool, not a dialect validator.
- Why are my comments and strings left exactly as written?
- Because changing them could change behavior or meaning. A string like '-- not a comment' must stay exactly that, and a real comment should keep its text. The tokenizer isolates them so the formatter never touches their contents.
- Can it uppercase or lowercase keywords?
- It can uppercase recognized keywords (the common convention that makes SELECT, FROM, and WHERE pop), controlled by a toggle. Turn it off to leave keyword case exactly as you typed it.
- Does it validate my SQL?
- No. It does not check that your query is syntactically or semantically correct — it just formats whatever you give it. Run the query against your database (or a linter) to validate it.
- Is my SQL sent to a server?
- No. Parsing and formatting happen entirely in your browser with no network request, so queries with confidential schema or data stay local.