SQL Formatter
Format and beautify SQL queries for various dialects.
Input SQL
Formatted SQL
SELECT * FROM users WHERE id = 1
SQL formatting: what it fixes, what it cannot
SQL is easy to write on one line and hard to read on one line. A query lifted from an application log, an ORM debug trace or a colleague's chat message usually arrives as a single run of text with inconsistent casing and no structure. A formatter puts each clause on its own line, breaks column lists one item per line, indents subqueries, CTEs and window functions, and leaves the meaning untouched. The result is not prettier for its own sake: it makes a wrong join condition, a missing WHERE or an accidental cartesian product visible in code review.
This page uses the sql-formatter library in your browser. Paste a statement, choose the dialect (Standard SQL, PostgreSQL, MySQL, T-SQL for SQL Server, or PL/SQL for Oracle) and click Format. Keyword case is preserved exactly as you typed it, indentation is two spaces, and a script with several statements separated by semicolons comes back with a blank line between them. The query is parsed, never executed, and never sent to a server.
Before and after
-- input
select o.id, c.name, sum(oi.qty * oi.price) as total from orders o join customers c on c.id = o.customer_id join order_items oi on oi.order_id = o.id where o.status = 'paid' and o.created_at >= '2026-04-01' group by o.id, c.name having sum(oi.qty * oi.price) > 5000 order by total desc limit 20
-- output
select
o.id,
c.name,
sum(oi.qty * oi.price) as total
from
orders o
join customers c on c.id = o.customer_id
join order_items oi on oi.order_id = o.id
where
o.status = 'paid'
and o.created_at >= '2026-04-01'
group by
o.id,
c.name
having
sum(oi.qty * oi.price) > 5000
order by
total desc
limit
20Why the dialect matters
The formatter needs to know which words are keywords and how identifiers are quoted, and the databases disagree:
| Feature | PostgreSQL / standard | MySQL | SQL Server (T-SQL) | Oracle (PL/SQL) |
|---|---|---|---|---|
| Quoted identifier | "order" | `order` | [order] | "ORDER" |
| Row limit | LIMIT 10 or FETCH FIRST 10 ROWS ONLY | LIMIT 10 | TOP 10 or OFFSET ... FETCH | FETCH FIRST 10 ROWS ONLY (12c and later) |
| String concatenation | || | CONCAT() | + or CONCAT() | || |
| Current time | now() | NOW() | GETDATE() | SYSDATE |
| Auto-increment key | GENERATED ... AS IDENTITY | AUTO_INCREMENT | IDENTITY(1,1) | GENERATED ... AS IDENTITY |
Pick the wrong dialect and the formatter may split a bracketed T-SQL identifier or treat a backtick as an error. Batch separators such as SQL Server's GO are commands for the client tool rather than SQL, so remove them before formatting and put them back afterwards. PostgreSQL folds unquoted identifiers to lower case, while MySQL table names can be case-sensitive on Linux depending on server configuration, which is one reason to keep every identifier in one consistent case across a codebase.
Style choices worth agreeing on
- Keyword case. Upper-case keywords with lower-case identifiers is the most common convention. This formatter preserves whatever you typed, so apply the casing in your editor or with a linter.
- Comma position. Trailing commas read naturally; leading commas make it easier to comment out one column. Either works if everyone uses the same one.
- Explicit joins. Write
JOIN ... ONrather than listing tables with commas and filtering in WHERE; formatted output then shows each relationship on its own line. - CTEs over nesting. A
WITHclause named for what it computes is easier to review than a subquery three levels deep. - No SELECT *. Naming columns keeps the query stable when the table changes and makes the formatted column list a useful summary.
For automated enforcement, SQLFluff lints and fixes SQL in CI across many dialects, pgFormatter (pg_format) is a fast command-line formatter for PostgreSQL-style SQL, and the Python package sqlparse installs a sqlformat command:
pip install sqlparse
sqlformat -r -k upper query.sql # reindent, upper-case keywords
pip install sqlfluff
sqlfluff fix --dialect postgres models/ # rewrite files in place
sqlfluff lint --dialect mysql query.sqlFormatting is not validation
A formatter tokenises text. It does not know whether the table exists, whether customer_id is the right column, whether the join multiplies rows or whether the query will take four hours. Perfectly formatted SQL can still be wrong. Run it against a staging database, read the plan with EXPLAIN (or EXPLAIN ANALYZE in PostgreSQL), and keep the formatted version in the pull request so reviewers read the same layout you did. Whitespace does not change the execution plan, although some engines key their plan cache on the exact statement text, so formatting queries consistently at the application layer helps cache hits.
Never format your way into string concatenation
If a query contains a value that came from a user, it must be passed as a parameter ($1, ?, @name or :name depending on the driver), never pasted into the SQL text. The formatter keeps placeholders intact, so format the template and bind the values separately. The guide Preventing SQL Injection shows the safe pattern for each major language.Getting the SQL out of your ORM
Most of the queries that need formatting were never typed by a human. Django exposes str(queryset.query) and queryset.explain(), Rails has relation.to_sql, Hibernate logs statements with hibernate.show_sql, Prisma and Sequelize both offer query logging, and every database can log slow queries on its own side. Paste the captured statement here, format it, and the N+1 or the missing index usually jumps out. Remove real customer values from the literals before you share the formatted query in a ticket or a chat channel.
How to use
- Paste one statement or a whole script into the input panel.
- Choose the dialect that matches your database: Standard SQL, PostgreSQL, MySQL, T-SQL or PL/SQL. This decides how quoted identifiers and dialect keywords are handled.
- Click Format. Each clause moves to its own line, column lists are split one per line and subqueries are indented by two spaces.
- Read any error shown in the output panel; it usually points at a stray quote, an unbalanced bracket or a client-only command such as GO.
- Click Copy and paste the formatted SQL into your migration, pull request or ticket. Keyword case is kept exactly as you typed it.
Common use cases
- Reading a one-line query captured from an application log or a slow-query log.
- Cleaning up ORM-generated SQL before attaching it to a performance ticket.
- Reformatting a stored procedure or view definition pulled from a legacy SQL Server database.
- Making a 300-character analytics query reviewable in a pull request.
- Teaching: turning a compact example into a layout where each clause is visible.
- Comparing two versions of a query after formatting both, using the Text Diff tool.
Frequently asked questions
Does the formatter run my query?
Why did the keyword case not change?
Which dialect should I pick?
Why does formatting fail on my SQL Server script?
Can it format multiple statements at once?
Will formatting change what the query returns?
Are placeholders like $1, ? and :name preserved?
Advertisement