SQL Formatter
Format messy SQL into clean, indented statements or minify it to a single line. Handles strings, comments, identifiers and subqueries. No upload.
SQL
How it works
- A real tokenizer walks the SQL character by character, respecting single-quoted strings (with
''escapes), double-quoted identifiers, backtick and[bracketed]identifiers,--line comments,/* block */comments, numbers and punctuation. - Main clauses (
SELECT,FROM,WHERE,JOIN,GROUP BY,ORDER BY,HAVING,LIMIT,UNION,INSERT INTO,VALUES,UPDATE,SET,DELETE FROM,ON…) start a new line;AND/ORinsideWHERE/ONare indented one extra level and aligned. - Commas stay at the end of the line, subqueries are indented by parenthesis depth, and strings, comments and identifiers keep their original case.
- Minify strips whitespace and newlines outside strings and comments, keeping just enough spacing between tokens — the statement stays executable, just compact.
About SQL Formatter
SQL written by hand, dumped by ORMs, or pasted out of logs is almost always a single cramped line or an inconsistent jumble of casing and indentation. Formatting it safely is harder than it looks — a naive regex that adds newlines before keywords will happily split string literals that happen to contain those words. This tool tokenizes first, so quoted strings, comments and identifiers are treated as opaque units and never broken apart.
The same token stream powers the minifier, which collapses whitespace while keeping keyword/identifier boundaries distinct, so the minified statement parses identically. Use Format to review and edit your query, then Minify to shrink it for embedding in code, configuration files or logs. Both directions preserve comments, string content and identifier casing exactly as written.
Lexing is the part that has to be right
Everything runs off a token stream produced by a character scanner that classifies whitespace, single-quoted strings with `''` doubling, double-quoted and backtick and bracketed identifiers as opaque tokens, line comments, block comments, numbers including a decimal point and an exponent, words starting with a letter or `_`, `$` or `#`, and single-character punctuation. Nothing after that stage looks at raw characters again.
This is why a regular expression cannot do the job. `SELECT` inside a string literal, a `--` inside a quoted value, a comma inside a bracketed identifier — a regex that inserts a newline before each keyword corrupts all three, and the corruption is silent because the result still looks like SQL. Scanners also differ on dialect quoting in a way that matters: backticks and square brackets are treated as identifier delimiters even though only SQL Server uses the latter, so a MySQL query survives a round trip intact.
Layout comes from a clause table, not from a grammar
Line breaks are driven by a list of multi-word clause phrases matched greedily longest-first, so `LEFT OUTER JOIN` wins over `LEFT JOIN` wins over `JOIN`. Indentation is parenthesis depth times the indent width, plus one extra level inside a top-level select list. Commas end a line, so each selected column sits on its own row. Minify reuses the same token stream, re-inserting a space only where two word-like tokens would otherwise merge into one identifier.
`AND` and `OR` break onto a new indented line only while a logical context flag is set, turned on by `WHERE`, `ON` and `HAVING` and cleared by the next main clause — so boolean structure is indented where it is meaningful and left alone inside a `CASE` expression. Parentheses are inspected rather than assumed: a `(` is a subquery boundary only when the next token is `SELECT`, `INSERT`, `UPDATE`, `DELETE`, `WITH` or `VALUES`, which is why `IN (SELECT ...)` splits across lines while `COUNT(*)` stays inline.
Limits worth knowing before you paste production SQL
There is no dialect selector, and the keyword table is generic. A column named `key`, `order` or `end` is recognised as a keyword and upper-cased when that option is on — harmless, since SQL keywords are case-insensitive. Identifier case and string contents are never altered, so quoted identifiers come through unchanged.
Two lexical gaps are real. MySQL's `#` line comment is not recognised, because `#` is treated as a word character: `# note` lexes as the word `#` followed by `note` and gets laid out as code. And backslash escapes inside string literals are unhandled — under MySQL defaults `'a\'b'` is one string containing an escaped quote, but the scanner ends the literal at the backslash-quote pair, so the remainder is re-tokenised and the layout goes wrong.
Finally, this tool does not validate. It will happily lay out a statement with a syntax error and produce well-formatted nonsense, because its only failure mode is an internal exception rather than a grammar check. Comments survive both directions, including `--` line comments in minified output where a newline is forced so the rest of the statement is not swallowed.
Frequently Asked Questions
How do I format SQL online?
Does it validate my SQL syntax?
Is my data sent to a server?
Do I need an account or API key?
Can I use these tools offline?
All processing happens in your browser. No uploads, no tracking, no servers. Your API keys, configs, and private payloads stay private — 100% client-side.