bitlvl
EN

SQL formatter

Paste a query, a migration or a whole dump of statements. Keywords are re-cased, clauses go on their own lines, subqueries, CTEs, CASE expressions and JOIN conditions are indented, and strings, identifiers and comments are left exactly as they were. Works for PostgreSQL, MySQL/MariaDB, SQLite and SQL Server syntax.

What the formatter does

  • Clauses (SELECT, FROM, WHERE, GROUP BY, ORDER BY, SET, VALUES, RETURNING…) each start a line; their content is indented underneath, one item per line for lists.
  • Joins start a line at the clause level; the ON condition stays with the join and further AND/OR terms indent under it.
  • Subqueries and CTEs open a parenthesised block whose content is indented one level; short parenthesised lists (IN ('a', 'b'), function arguments, tuples) stay on one line.
  • CASE expressions put each WHEN and the ELSE on their own line and align END with CASE.
  • Window functions keep OVER (PARTITION BY … ORDER BY …) on one line when it fits.
  • CREATE TABLE writes one column definition per line; INSERT … VALUES writes one tuple per line.
  • Statements are separated by a blank line after each semicolon.

What it never touches

String literals ('it''s', E'\n', $$ … $$), quoted identifiers ("Name", `name`, [name]), comments (--, #, /* */) and parameters (?, $1, :name, @var) are copied byte for byte. Only whitespace and the case of keywords change, so the formatted query is the same query. Keyword re-casing applies to SQL keywords and standard functions (COUNT, COALESCE, NOW…), not to your own identifiers: my_table stays my_table even in upper-case mode.

Trailing or leading commas

Trailing commas (a, at the end of a line) are what most style guides and ORMs produce. Leading commas (, b at the start) make it possible to comment out any line of a select list except the first without breaking the query, which is why they are popular in analytics SQL. Pick whichever your team reads faster; the formatter converts between them.

Minify

Minify collapses everything to one line with single spaces, turning line comments into block comments so they survive. Use it for log lines, URL parameters, or pasting a query into a chat without the newlines being eaten.

Dialects

The tokenizer understands PostgreSQL (:: casts, $1 parameters, dollar quoting, ->> JSON operators, FILTER, RETURNING, ON CONFLICT), MySQL/MariaDB (backtick identifiers, # comments, STRAIGHT_JOIN, ON DUPLICATE KEY UPDATE, LIMIT x OFFSET y), SQLite and SQL Server ([bracket] identifiers, @variables, TOP, CROSS APPLY). It does not validate the SQL; a query with a syntax error is formatted on a best-effort basis so you can still read it.

Formatting SQL elsewhere

# PostgreSQL: pg_format (pgFormatter, Perl)
pg_format -s 2 -u 1 query.sql

# any dialect: sqlfluff (Python), also lints
sqlfluff fix --dialect postgres query.sql

# JavaScript: sql-formatter
npx sql-formatter -l postgresql query.sql

Questions

Does it change what the query does?

No. Only whitespace and keyword case change; literals, identifiers, comments and parameters are copied unchanged. Re-casing applies to keywords and standard function names, which are case-insensitive in every SQL dialect.

Why is a subquery on several lines when it is short?

Any parenthesised group that contains a clause keyword (SELECT, FROM, WHERE…) is written as a block, because that is what makes nested queries readable. Function arguments, IN lists and VALUES tuples stay inline when they are short.

Can it format PL/pgSQL functions or stored procedures?

The body of a function in $$ … $$ is a string literal to the formatter and is left as is. The CREATE FUNCTION statement around it is formatted. Full procedural-language formatting is out of scope.

Is my SQL sent to a server?

No. The page runs entirely in your browser, which is the point for queries that contain production table names or literals.

What about EXPLAIN output?

That is a different tool: paste the plan into the EXPLAIN visualizer, which draws the tree and flags the misestimates.