SQL Formatter

Format a SQL query into something readable, or collapse it back to one line. Pick one of twelve dialects, because a backtick quotes an identifier in MySQL and is a syntax error in PostgreSQL.

SQL Input
Formatted SQL

1 SQL Formatter example

One long line

1
select u.id,u.name,count(o.id) as orders,sum(o.total) as spent from users u left join orders o on o.user_id=u.id where u.created_at>='2026-01-01' and u.active=true group by u.id,u.name having count(o.id)>2 order by spent desc limit 20;

Formatted

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
SELECT
  u.id,
  u.name,
  count(o.id) AS orders,
  sum(o.total) AS spent
FROM
  users u
  LEFT JOIN orders o ON o.user_id = u.id
WHERE
  u.created_at >= '2026-01-01'
  AND u.active = TRUE
GROUP BY
  u.id,
  u.name
HAVING
  count(o.id) > 2
ORDER BY
  spent DESC
LIMIT
  20;

2 Pick the right dialect

Pick the dialect your database speaks. Dialects disagree about more than keywords. MySQL quotes identifiers with backticks, PostgreSQL and standard SQL use double quotes, and SQL Server uses square brackets. With the wrong dialect, the formatter can misread a quoted identifier as a string, or a string as an identifier, and the result may not run.

The rest works the same in every dialect: the tokens stay as they are and only the whitespace moves. No clause is reordered, no join is rewritten and nothing is added. Uppercase keywords against lowercase identifiers is the usual convention, because the SELECT, FROM and WHERE lines then show the shape of a long query before you read it.

3 Notes

Placeholders survive

?, $1, :name and @name pass through untouched, so a parameterized query stays parameterized. Pasting values into SQL is how injection happens, so bind them instead.

Comments are kept

Format keeps both -- line comments and /* block */ comments where they were. Minify drops -- comments, because on a single line they would comment out everything after them.

Procedural code is rough

The formatter is built for queries. PL/pgSQL bodies, T-SQL control flow and stored procedures still come out valid, but sometimes oddly indented.

Minify for embedding

The Minify button collapses the query to one line for a string literal or a log line. It also collapses runs of spaces inside string literals, so keep the formatted version if a value depends on them.

How to use the SQL Formatter tool

  1. Paste a query, or load a file with Upload SQL.
  2. Choose the Dialect that matches your database. It changes how identifiers and quotes are read, as well as which words count as keywords.
  3. Keywords sets UPPERCASE, lowercase or As written, and Indent picks 2 Spaces, 4 Spaces or Tab.
  4. Format lays the query out, and Minify collapses it to one line for embedding in a string. Minify drops -- comments, since on one line they would swallow the rest of the query.

How to format SQL in a project

Command line and pre-commit

# npm i -D sql-formatter
npx sql-formatter -l postgresql --fix migrations/*.sql

# sqlfluff both lints and formats, and understands more dialects
pip install sqlfluff
sqlfluff format --dialect postgres queries/
sqlfluff lint --dialect postgres queries/

# .pre-commit-config.yaml
# - repo: https://github.com/sqlfluff/sqlfluff
#   rev: 3.2.5
#   hooks:
#     - id: sqlfluff-format
#       args: [--dialect, postgres]

JavaScript / Node.js

// npm i sql-formatter
const { format } = require("sql-formatter");

console.log(format(query, {
    language: "postgresql",
    keywordCase: "upper",
    tabWidth: 2,
}));

// Formatting is cosmetic. This is the part that matters:
// never build SQL by concatenating values.
await client.query(
    "SELECT * FROM users WHERE email = $1 AND active = $2",
    [email, true],
);

Python

# pip install sqlparse
import sqlparse

print(sqlparse.format(
    query,
    reindent=True,
    keyword_case="upper",
    indent_width=2,
))

# Parameterised, always
cur.execute(
    "SELECT * FROM users WHERE email = %s AND active = %s",
    (email, True),
)

Common errors and how to fix them

A quoted identifier was mangled
The dialect is wrong. MySQL quotes identifiers with backticks, PostgreSQL with double quotes and SQL Server with square brackets, and each dialect reads the others' quotes as something else.
A stored procedure came out badly indented
The formatter targets queries, and it only partly understands PL/pgSQL and T-SQL control flow. The SQL still runs; it only looks worse than it should.
Placeholders were rewritten
They should not be: ?, $1, :name and @name all pass through untouched. If yours changed, pick a dialect that uses that placeholder style.
Formatting changed the results
Format cannot do that, because only whitespace moves. If results differ, something else changed, most likely a value you pasted in rather than bound. Minify, however, collapses runs of spaces inside string literals, so compare the literals first.

Good to know

Write keywords in uppercase and identifiers in lowercase. The SELECT, FROM, WHERE and JOIN lines then form a skeleton you can follow without reading every token. The habit comes from terminals without syntax highlighting, and it still helps in a log file, a migration diff or a code review comment, none of which are highlighted either.

Specifications and references

This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.

Frequently Asked Questions

Which dialects are supported?

PostgreSQL, MySQL, MariaDB, SQLite, SQL Server (T-SQL), BigQuery, Snowflake, Redshift, Db2, Hive, Spark and standard SQL. Pick the one your database uses, because dialects disagree about quoting, and the wrong choice can mangle an identifier.

Will it change what my query does?

No. Format reprints the same tokens with different whitespace. It does not rewrite joins, reorder clauses or add anything, and string literals stay exactly as they are.

Can it uppercase the keywords?

Yes, and it can also lowercase them or leave them as written. Uppercase keywords against lowercase identifiers is the most common convention, because it makes the shape of a long query readable at a glance.

Does it handle placeholders?

Yes. ?, $1, :name and @name all survive formatting, so a parameterized query stays parameterized. Never build a query by pasting values into it; that is where most SQL injection comes from.

Why did my stored procedure come out oddly?

The formatter is built for queries. Procedural blocks, PL/pgSQL bodies and vendor-specific control flow are only partly understood and can end up oddly indented. The SQL still runs; it only looks worse than it should.

Related

To load data rather than query it, CSV to SQL INSERT turns a spreadsheet export into statements. Results usually come back as JSON, which the JSON formatter and JSON table viewer handle.

More Code Formatters & Beautifiers

Browse all code formatters & beautifiers

Copied to clipboard!