Skip to content
SQLCraft
  • 100% client-side isolated
  • no upload
  • semantic guard included

Format the statement, and keep its meaning

Pretty-print SQL with clause phrases on their own line, leading or trailing commas and a line-length limit — or minify it back to one line. The token stream is compared before and after, so a reformat can never change what the query means.

Examples

Your SQL

Tokenized exactly as the target engine reads it.

1 line · 331 characters

Output

Clause phrases start a line; commas break only inside a list.

SELECT
  c.id,
  c.email,
  count(o.id) AS orders,
  sum(o.total) AS revenue
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE c.country IN ('Spain', 'Portugal', 'Italy')
  AND o.status NOT IN ('cancelled', 'refunded')
  AND o.placed_at >= '2024-01-01'
GROUP BY c.id,
  c.email
HAVING count(o.id) > 2
ORDER BY revenue DESC
LIMIT 25;
Statements
1
Keywords
16
Lines
1 → 15
One line
+1%

334 chars minified

Layout rules

Every switch changes only the layout — the token stream is compared before the result is shown.

Semantics preserved
Indent
Keywords
Commas
Blank line between statements
Re-case built-in functionscount, sum, coalesce, now…
Keep comments when minifyingA line comment survives as a block comment

PostgreSQL reads the formatted statement exactly like the input: 16 keywords recognised, every other token byte-identical.

Laid out in 0.00 ms on this device. Press CtrlEnter to format immediately instead of waiting for the debounce.

A tokenizer, not a search-and-replace

Before a single space moves, the query is split into tokens: strings, quoted identifiers, line and block comments, dollar-quoted bodies, numbers and operators. That is why a comma inside a string literal is never treated as a list separator, and why a comment cannot be orphaned from the line it explains.

Layout follows structure, then length

Clause phrases start their own line, subqueries and definitions get their own indent, and booleans break only at their own depth — so a BETWEEN … AND is never mistaken for a continuation. Only afterwards does the line-length limit wrap whatever is still long, and the count of wrapped lines is reported.

The check is the feature

Every format compares the token stream before and after against the dialect's keyword set: keywords are compared case-insensitively and everything else byte for byte. A layout that would change the statement is withheld with an explanation instead of being shown as if it were safe.

  • Dialect Converter

    Move one query between six engines and get the spellings that actually differ: identifier quoting, string escaping, boolean literals, type names, auto-increment columns and the LIMIT / TOP / FETCH FIRST family. What cannot be translated — ILIKE, JSONB operators, QUALIFY, ON CONFLICT — is listed as a gap instead of being silently dropped.

    Open tool
  • JSON / CSV to SQL

    Paste an API response, one JSON object per line, or a CSV export and get a CREATE TABLE with types inferred from the values rather than declared up front: sizes come from the longest string, a date that meets a timestamp widens to a timestamp, and every substitution or renamed key is reported. The INSERT statements follow, batched or one per row.

    Open tool
  • Mock Data

    Pick a preset table — users, orders, products or subscriptions — set a row count and a seed, and get rows that hold together: an email built from the same row's names, a status from a small vocabulary, dates that never read the clock. Four presets, twenty-three column kinds and one identical result per seed.

    Open tool

SQL formatter FAQ

Line-break rules, the line-length limit, keyword casing, comma style and what the minifier keeps.

How does the formatter decide where a line breaks?

Clause phrases that belong together are treated as one unit, so LEFT OUTER JOIN or ORDER BY starts a line rather than leaving the preposition behind. Boolean operators break only at their own nesting depth, a comma breaks a line only inside the list it belongs to, and a subquery or a definition gets its own indent. A final pass wraps any line that still exceeds the limit you set.

What does the line-length limit do?

It is a safety net, not the main rule. Layout happens first from the structure of the query; then any line longer than the limit is split at its best break point, and the count of wrapped lines is reported in the stats. Setting the limit to 0 disables wrapping entirely, which is useful when you want the structural layout only.

Can I keep my keyword casing instead of forcing it?

Yes. Keyword casing has three modes: upper, lower and preserve. In preserve mode nothing that is recognised as a keyword is re-cased — and an identifier that is quoted is never re-cased in any mode, because MySQL and PostgreSQL disagree about which words are reserved and a quoted name is the one the author chose deliberately.

What is the difference between trailing and leading commas?

Both produce valid SQL; they differ in where the separator sits. Trailing commas end each item, which is the common style in PostgreSQL documentation. Leading commas put the comma at the start of continuation lines, which makes it obvious when an item is added or removed. The choice changes only the layout, never the token stream.

What does the minifier do with comments?

By default it removes them and collapses the statement onto one line with the minimum spacing the dialect needs — for example a space between two words, none before a comma or a closing parenthesis. A line comment can be preserved as a block comment inside the collapsed output, which is what you want when a comment documents a deliberate workaround.