SQL Formatter

Paste a one-line SQL statement copied from a log or an ORM, and the formatter breaks it into indented clauses with consistent keyword casing, newlines before SELECT, FROM, WHERE, GROUP BY, and aligned columns in the projection. Supports MySQL, PostgreSQL, SQL Server, Oracle, SQLite and BigQuery dialects, each has slightly different keywords and reserved words.

How formatting works

  1. 1

    Paste your SQL

    Single-line blob, minified output from Hibernate, whatever. Multiple statements separated by `;` are all formatted.

  2. 2

    Pick dialect and style

    Dialect controls keyword list; style controls comma placement (leading vs trailing), indent width, and uppercase/lowercase keywords.

  3. 3

    Tokens are parsed, not regex-replaced

    A tokenizer handles strings, comments, parentheses and subqueries correctly. String literals are preserved verbatim.

  4. 4

    Copy the formatted output

    Validated SQL: same semantics, cleaner layout.

Before and after

Before:

SELECT u.id,u.name,COUNT(o.id) AS orders FROM users u LEFT JOIN orders o ON o.user_id=u.id WHERE u.created_at>='2024-01-01' GROUP BY u.id,u.name HAVING COUNT(o.id)>5 ORDER BY orders DESC LIMIT 50;

After (leading comma, uppercase keywords, 2-space indent):

SELECT
    u.id
  , u.name
  , COUNT(o.id) AS orders
FROM users u
LEFT JOIN orders o
  ON o.user_id = u.id
WHERE u.created_at >= '2024-01-01'
GROUP BY u.id, u.name
HAVING COUNT(o.id) > 5
ORDER BY orders DESC
LIMIT 50;

Style choices that matter

  • Uppercase vs lowercase keywords. UPPERCASE is traditional and scannable. Lowercase is cleaner in modern code editors with syntax highlighting.
  • Leading vs trailing commas. Leading ( , col) makes it easier to comment out a single column. Trailing (col,) reads more naturally in text.
  • Comma placement in GROUP BY. Often one per line for long clauses, inline for short ones.
  • JOIN indentation. ON on the next line (hanging indent) vs on the same line. Long conditions benefit from hanging.
  • Subqueries. Indent the whole subquery, not just the opening paren.

Dialect-specific gotchas

  • MySQL backticks vs PostgreSQL double-quotes for identifiers.
  • WITH CTEs, MS SQL has a ; requirement before WITH; the formatter handles it.
  • Window functions, long OVER (...) clauses benefit from line-wrapped PARTITION BY and ORDER BY.
  • BigQuery has ARRAY_AGG, STRUCT and table suffixes (*_yyyymmdd) that the tokenizer must not break.
  • Oracle has (+) outer-join syntax, the formatter preserves it but flags it as legacy.

What the formatter does not do

  • Fix bugs, an invalid JOIN stays invalid.
  • Expand SELECT *, column lists are not inferred from schema.
  • Optimize queries, layout only, not execution plans.
  • Rewrite subqueries as CTEs, a different concern.

Frequently Asked Questions

No, it is purely cosmetic. Whitespace, newlines and comma placement move around, but keywords, operators, literals and identifiers are preserved exactly.

Supported, CREATE TABLE, ALTER, CREATE PROCEDURE, triggers. The formatter handles block constructs (BEGIN ... END) and line continuations inside procedures.

It should not, if it does, it is likely a dialect mismatch. Try switching dialect. Please report persistent failures; we treat them as bugs.

Flink SQL and Cassandra CQL look similar but have dialect-specific keywords that mainstream formatters mangle. Use with caution and verify the output runs.

Related Tools

Tool available in other languages