Format SQL
Formatted SQL appears here.
Input is capped at 100,000 characters. Longer input is cut at that point, and the result says so. Format keeps comments where they are. Minify removes them. The formatter never changes a string, a quoted name, a number, or a parameter, and it re-reads its own output to check.
How to format SQL
- Paste the query. A one-liner from a log works, and so does a whole script with several statements.
- Pick the dialect. Postgres, MySQL, and the rest differ in keywords and quoting, and the dialect tells the formatter which words are keywords.
- Pick the keyword case and the indent. Uppercase keywords with two spaces is the usual house style.
- Press Format SQL. Minify does the opposite: one line, comments removed, ready to paste into code or a config file.
- Copy the result, or download it as a .sql file. Read the notes under the result: the formatter reports unbalanced parentheses and joins without a condition.
What the formatter changes
Formatting only moves whitespace and changes keyword case. The query means the same after formatting as it did before.
| What changes | How |
|---|---|
| Line breaks | Each major clause (SELECT, FROM, WHERE, GROUP BY, ORDER BY, and the rest) starts a new line. |
| Lists | SELECT, GROUP BY, and ORDER BY lists get one item per line. |
| Indentation | Subqueries, CASE branches, and parenthesised groups indent one level. |
| Keyword case | Recognised keywords follow the case you pick. Names, strings, and comments keep the case you typed. |
| What never changes | Strings, quoted names, numbers, and parameters are copied exactly. |
| Minify | Comments are removed and all whitespace collapses to single spaces. |
A parenthesised group stays on one line when it is short, and breaks across lines when it holds a subquery or runs long. A CASE expression breaks across lines too: WHEN and ELSE each start a line, and END lines up with CASE.
Dialects
The dialect changes which words count as keywords and how quoting is read. The shared core of SELECT, JOIN, WHERE, and GROUP BY formats the same in all of them.
| Dialect | Extra keywords recognised | Quoting |
|---|---|---|
| Standard SQL | The shared core | Double quotes for names |
| PostgreSQL | RETURNING, DISTINCT ON, ON CONFLICT, dollar-quoted strings | Double quotes; :: casts |
| MySQL | AUTO_INCREMENT, ON DUPLICATE KEY UPDATE, STRAIGHT_JOIN | Backticks; double quotes are strings |
| MariaDB | Same as MySQL | Backticks; double quotes are strings |
| SQLite | AUTOINCREMENT, WITHOUT ROWID, PRAGMA | Double quotes, brackets, or backticks |
| SQL Server (T-SQL) | TOP, IDENTITY, NOLOCK hints | Square brackets; N'...' strings |
| Oracle (PL/SQL) | ROWNUM, CONNECT BY, MINUS | Double quotes for names |
| BigQuery | STRUCT, UNNEST, QUALIFY | Backticks for names |
| Snowflake | QUALIFY, SAMPLE, FLATTEN | Double quotes for names |
Pick Standard SQL when the query has to run on more than one database. It follows the lexical rules the dialects share, and understands the common quoting styles: double quotes, backticks, square brackets, E'...' and $$...$$ strings, the :: cast, and ?, :name, @name, and $1 parameters.
Checks the formatter runs
The formatter checks structure as it formats. It does not run the query and it does not know your schema, so it can only flag what the text itself shows.
Unbalanced parentheses
An opening parenthesis with no close is reported with the line where it opens. An extra closing parenthesis is reported the same way.
Unclosed strings
A string or quoted name that never closes stops the format, and the error names the line.
Joins without a condition
A JOIN with no ON or USING after it is flagged. Without a condition, a join pairs every row with every row. CROSS JOIN is the exception: it means that on purpose.
Literal check
After formatting, the page reads its own output back and compares every string, quoted name, number, and parameter with the input. If anything changed, the original is shown instead, with a warning.
What it does not check
Column names, table names, and types are not checked. A query can format cleanly and still fail against a real database.
What it will not do
This is a pretty-printer. It does not execute SQL, connect to a database, or check a query against a schema.
Procedural code passes through: the body of a PL/pgSQL function or a T-SQL BEGIN...END block is copied as-is and may not re-indent beyond the surrounding statement. Dollar-quoted bodies are treated as one string and never split.
Input is capped at 100,000 characters. Longer input is cut at that point, and the result says so.
Format SQL in code
Use a maintained library in production. This page's own formatter is a small tokenizer written for the browser, not a full parser.
Python, with sqlparse
import sqlparse
print(sqlparse.format(sql, reindent=True, keyword_case="upper"))
JavaScript, with sql-formatter
import { format } from "sql-formatter";
format(sql, { language: "postgresql", keywordCase: "upper" });
Shell, with the sqlformat command
sqlformat --reindent --keywords upper query.sql > formatted.sql
sqlformat ships with sqlparse. It reads a file and writes the formatted query.
Frequently asked questions
Does formatting change what my query does?
No. Formatting changes whitespace and, if you ask for it, the case of keywords. Strings, quoted names, numbers, and parameters are copied exactly, and the page re-reads its output to confirm they survived. A query that ran before formatting runs the same after it.
Which SQL dialects does it support?
Standard SQL, PostgreSQL, MySQL, MariaDB, SQLite, SQL Server (T-SQL), Oracle (PL/SQL), BigQuery, and Snowflake. The dialect changes which words count as keywords and how quoting is read. The shared core of SELECT, JOIN, WHERE, and GROUP BY formats the same in all of them.
Does it validate my SQL?
No. It checks structure: unbalanced parentheses, unclosed strings, and JOINs without ON or USING. It does not check column names, table names, or types, and it never runs the query. A query can format cleanly and still fail against a real database.
Is my SQL uploaded anywhere?
No. Formatting runs in the browser on your machine. The query is not sent to a server, stored, or logged, and the page works offline once it has loaded. That is why it is safe to paste queries that name production tables.
Why did a word stay lowercase when keywords are uppercase?
Keyword case applies only to recognised keywords. Names, type names the formatter does not list, and function names keep the case you typed. A column called name stays name, and a type called jsonb stays jsonb.
Can I format SQL copied from a log file?
Yes. Tick "Strip log prefixes" before formatting. It removes a leading timestamp and log level from each line, such as "2026-11-08 10:23:11 INFO". Lines that do not start with a timestamp are left alone, and the page reports how many lines were cleaned.
Sources
PostgreSQL documentation, SELECT: the SELECT syntax this page follows for Postgres, including DISTINCT ON, RETURNING, and window functions.
MySQL documentation, SELECT Statement: the SELECT syntax for MySQL, including STRAIGHT_JOIN and the LIMIT offset form.
SQLite documentation, SELECT: the SELECT syntax for SQLite.
sqlparse documentation, sqlparse: the Python SQL formatter, including the reindent and keyword_case options shown in the code section.
sql-formatter on npm, sql-formatter: the JavaScript formatter, including the language and keywordCase options shown in the code section.
Agents
Machine readable summary for AI assistants: