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
  20

Why the dialect matters

The formatter needs to know which words are keywords and how identifiers are quoted, and the databases disagree:

FeaturePostgreSQL / standardMySQLSQL Server (T-SQL)Oracle (PL/SQL)
Quoted identifier"order"`order`[order]"ORDER"
Row limitLIMIT 10 or FETCH FIRST 10 ROWS ONLYLIMIT 10TOP 10 or OFFSET ... FETCHFETCH FIRST 10 ROWS ONLY (12c and later)
String concatenation||CONCAT()+ or CONCAT()||
Current timenow()NOW()GETDATE()SYSDATE
Auto-increment keyGENERATED ... AS IDENTITYAUTO_INCREMENTIDENTITY(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 ... ON rather than listing tables with commas and filtering in WHERE; formatted output then shows each relationship on its own line.
  • CTEs over nesting. A WITH clause 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.sql

Formatting 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

  1. Paste one statement or a whole script into the input panel.
  2. 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.
  3. Click Format. Each clause moves to its own line, column lists are split one per line and subqueries are indented by two spaces.
  4. 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.
  5. 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?

No. It only tokenises and reformats the text in your browser. There is no database connection, so nothing can be read, changed or leaked; you can format a DELETE without a WHERE clause safely, although you should still not run one.

Why did the keyword case not change?

The formatter preserves the case you typed. If you want SELECT and FROM in upper case, type them that way, use your editor's transform-to-uppercase on the keywords, or run a linter such as SQLFluff that enforces a casing rule.

Which dialect should I pick?

Match your database: PostgreSQL for Postgres and most Postgres-compatible warehouses, MySQL for MySQL and MariaDB, T-SQL for SQL Server and Azure SQL, PL/SQL for Oracle, and Standard SQL when you are unsure or the query uses only common syntax.

Why does formatting fail on my SQL Server script?

The usual cause is the GO batch separator, which is a command for SQL Server Management Studio and sqlcmd rather than part of the language. Remove GO lines, format each batch, and put them back. Also check that the T-SQL dialect is selected so square-bracket identifiers are understood.

Can it format multiple statements at once?

Yes. Statements separated by semicolons are each formatted and separated by a blank line in the output, so a migration file with several CREATE and ALTER statements can be pasted in whole.

Will formatting change what the query returns?

No. Only whitespace and line breaks change; every token stays in place, including comments and placeholders. Whitespace does not affect the execution plan, so the formatted query performs exactly like the original.

Are placeholders like $1, ? and :name preserved?

Yes. Parameter markers are kept as they are, so you can format the query template used by your driver and keep binding values separately, which is the only safe way to handle user input in SQL.

Advertisement