SQL Formatter
Turn a wall of one-line SQL into indented, readable clauses — in the dialect you actually write.
Your SQL
Formatted SQL
SQL rarely arrives readable. It comes out of an ORM log on one enormous line, out of a stored procedure that three people have edited with three different tab settings, or out of a chat message where the newlines were eaten in transit. This formatter rebuilds the clause structure — one line per selected column, FROM, WHERE, GROUP BY and ORDER BY each on their own line, subqueries and CTEs indented inside their parentheses — so you can read the query before you have to reason about it.
The important control on this page is the dialect selector. SQL is not one language; it is a standard plus a dozen widely-used extensions that each added their own comment markers, quoting rules, pagination syntax and procedural blocks. Nineteen dialects are available here, and picking the right one is the difference between clean output and a parse error. Everything runs locally in your browser — a query is often the most sensitive thing on your screen, and this one never leaves the tab.
How to use the sql formatter
- 1
Pick your dialect first
Choose the engine the query is written for before you format. Standard SQL is a strict baseline and will reject MySQL
#comments, PostgreSQL dollar quotes and T-SQL square brackets. If you are unsure, choose the database you would run the query against. - 2
Paste, upload or drop the query
Multi-statement scripts are fine — statements are separated by semicolons and get a blank line between them. Comments are preserved in place.
- 3
Set indentation and keyword case, then copy
Two spaces, four spaces or tabs, and keywords upper-cased, lower-cased or left exactly as written. Output re-renders as you change the settings, so you can try both conventions before committing.
Why the dialect selector is not decoration
The formatter parses your SQL into tokens before it prints anything, and each dialect has its own token rules. Choose the wrong one and you get either a parse error or output that quietly misreads your query. Concretely:
- Comment markers. MySQL and MariaDB treat
#as a line comment. No other major dialect does, and standard SQL rejects the character outright. - Identifier quoting. MySQL uses backticks, T-SQL uses
[square brackets], and PostgreSQL, Oracle and SQLite use double quotes. BigQuery uses backticks but around a wholeproject.dataset.tablepath. - Pagination.
LIMIT 20, 10is MySQL.TOP 50is T-SQL.FETCH FIRST 50 ROWS ONLYis Oracle and Db2. Each is a different token sequence. - String and block syntax. PostgreSQL dollar quoting (
$$ … $$), OracleBEGIN … END; /blocks and T-SQLGObatch separators are all invisible to the generic parser. - Dialect-only clauses. Snowflake
QUALIFY, SparkDISTRIBUTE BYandLATERAL VIEW, PostgreSQLRETURNING, MySQLON DUPLICATE KEY UPDATE. If the parser does not know the keyword, it cannot give it its own line.
Getting it wrong fails in one of two ways. The loud failure is a parse error: paste a T-SQL query with [bracketed] identifiers while PostgreSQL is selected and the tokeniser stops at the first [ and tells you where. The quiet failure is worse. Format a MySQL upsert with SQLite selected and it does not error — it simply does not know that ON DUPLICATE KEY UPDATE is one clause, so it prints ON DUPLICATE KEY trailing off the VALUES line and starts a fresh line at UPDATE, which reads like a second statement. Your SQL is unchanged and still correct; the layout is actively misleading.
Standard SQL is the strictest option, not the most permissive one. It is the right choice for ANSI-portable queries and the wrong choice for anything vendor-flavoured. If a query fails to parse and you are confident the SQL is valid, the dialect selector is the first thing to check — the error you see is a tokeniser complaint about grammar, not a judgement about whether the query would run.
Choose your dialect page
Each of these pages carries the same engine with the dialect pre-selected, plus notes on the syntax that dialect handles differently and the specific quirks worth knowing about:
- MySQL — backtick identifiers,
LIMIT offset, count,#comments,ON DUPLICATE KEY UPDATE, storage engine and charset clauses onCREATE TABLE. - PostgreSQL — dollar-quoted function bodies,
::casts,RETURNING, JSONB operators such as->>and@>, array syntax and window functions. - T-SQL / SQL Server — square-bracket identifiers,
TOP,GObatches,MERGE, table variables and#temptables,WITH (NOLOCK)hints. - Oracle PL/SQL —
DECLARE … BEGIN … END;blocks, the/terminator,CONNECT BYhierarchies, the legacy(+)outer join operator andDUAL. - SQLite — type affinity and typeless columns,
AUTOINCREMENT,PRAGMAstatements,ON CONFLICTupserts, the narrowALTER TABLE. - BigQuery — backtick-quoted
project.dataset.tablepaths,STRUCTandARRAY,UNNEST, and formatting longWHEREclauses so partition filters are reviewable before you spend money. - Snowflake —
QUALIFY,LATERAL FLATTEN,VARIANTcolon paths, and time travel withATandBEFORE. - Spark SQL — HiveQL lineage,
LATERAL VIEW EXPLODE,DISTRIBUTE BYandCLUSTER BY,INSERT OVERWRITE, Delta LakeMERGE INTO.
Ten more dialects are available in the selector without a dedicated page: Redshift, MariaDB, Hive, Trino/Presto, ClickHouse, DuckDB, Db2, N1QL, TiDB and SingleStore. Nineteen in total, and the underlying library recognises a couple of aliases beyond that.
Every page runs the same engine with the same controls; only the pre-selected dialect and the notes differ. If you work across two databases — reading a Postgres query and porting it to BigQuery, say — formatting both in their own dialect first makes the structural differences the only differences left, which is much easier than diffing two arbitrary layouts.
What the formatter changes, and what it is not
Indentation is two spaces, four spaces or tabs. Two spaces suits queries with deep CTE chains or wide window functions, where four pushes the interesting part off the right edge of a review pane; four is the more common convention for stored procedures kept in a repository. The output re-renders immediately, so it costs nothing to look at both.
Keyword case is upper, lower or preserve, and it applies to reserved words only. Identifiers are never re-cased, and for good reason: PostgreSQL folds unquoted identifiers to lower case while the standard says fold to upper, and a quoted mixed-case identifier is a different name from the unquoted one. Re-casing could silently break a query, so it does not happen here.
Beyond those two settings the layout is fixed and opinionated: one selected column per line, top-level clauses on their own lines, subquery and CTE bodies indented inside their parentheses, comments left where you put them, and a blank line between statements. That is deliberate — a formatter is only useful in code review if two people running it on the same query get the same bytes out.
Underneath, this is a pretty-printer. It is built on the sql-formatter library, which tokenises your query and re-emits it with consistent whitespace and keyword casing. That is the whole job, and it is worth being precise about the boundaries:
- It does not validate that your query will run.
SELECT missing_column FROM no_such_tableformats perfectly. Semantic correctness needs a database, and this tool has none. - It never connects to a database. There is no credential field, no connection string, no server round trip. Nothing you paste is transmitted anywhere.
- It is not a linter. It will not tell you that a
LEFT JOINis being turned into an inner join by aWHEREpredicate, or that you are missing an index. Tools like sqlfluff exist for that. - It does run a light sanity check. An odd number of single quotes suggests an unterminated string literal, and unbalanced parentheses are counted and reported. Both surface as notes alongside the output rather than blocking it.
It also reports the dialect used, how many statements it found and how many lines the result is — enough to notice when you have pasted half a script.
SQL Formatter FAQ
Which dialect should I choose if I do not know?
Choose the database you would actually run the query against. If the query is genuinely portable ANSI SQL, Standard SQL gives the cleanest result. Note that Standard SQL is the strictest option — it rejects vendor extensions rather than tolerating them.
Does the formatter change what my query does?
No. Only whitespace, line breaks and keyword casing change. Identifiers, string literals, comments, hints and operators are re-emitted exactly as written. SQL keywords are case-insensitive, so casing them is safe; identifiers are left alone because in PostgreSQL and Oracle their case can be significant.
Why did my column alias get upper-cased?
Because it collides with a reserved word. An alias like month, year or level is a keyword in several dialects, so keyword casing applies to it. Set keyword case to Preserve, or quote the alias, if that matters to you.
Can it format a whole script with several statements?
Yes. Statements separated by semicolons are each formatted and separated by a blank line. T-SQL GO separators and Oracle slash terminators are kept on their own lines.
Will it tell me if my SQL is invalid?
Only partially, and it says so plainly. If the parser cannot tokenise the input in the chosen dialect you get an error pointing at the offending position — very often the fix is choosing a different dialect. Beyond that, it checks for unbalanced quotes and parentheses. It cannot tell you whether a table exists or a join is correct.
