Vibe Engines
YouTube

Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path

SQL Formatter

A lightweight SQL formatter. Paste a cramped, one-line query and get it back with each major clause on its own line, keywords cased consistently, and conditions indented — so you can actually read and review it. Runs in your browser; it formats for readability rather than parsing the full SQL grammar.

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.active = 1
  AND u.country IN ('US','CA')
GROUP BY u.id,
   u.name
HAVING COUNT(o.id) > 3
ORDER BY orders DESC
LIMIT 10

A query’s logic does not depend on its layout, but your ability to review it does. Paste a cramped one-line query and the tool rebuilds it with one clause per line, standard keywords in capitals and conditions indented beneath their clause. It is a fast, rule-based pass rather than a parser, and knowing its rules tells you when to trust it.

What it computes

The formatter applies seven text rules in a fixed order:

  1. Protect literals. Single-quoted strings, including '' escapes, double-quoted identifiers and backtick identifiers are set aside so no later rule can touch them.
  2. Collapse whitespace. Every run of spaces, tabs and newlines becomes one space.
  3. Uppercase keywords. A fixed list of 50 words, from SELECT and JOIN to COUNT, CASE and DESC, is capitalized wherever it appears as a whole word.
  4. Split top-level commas. A comma outside all parentheses ends the line, so each selected column or GROUP BY key gets its own row. Commas inside COUNT(...) or IN (...) are left alone.
  5. Break before clauses. 26 clause markers start a new line at the left margin, matched longest first so LEFT OUTER JOIN and DELETE FROM stay whole. They are the join forms, UNION, INTERSECT, EXCEPT, SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, INSERT INTO, VALUES, UPDATE and SET.
  6. Indent conditions. AND, OR and ON each start a line indented two spaces.
  7. Tidy and restore. Trailing spaces are trimmed, and the protected literals are put back exactly as typed.

A worked example

The default input is one 217-character line:

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.active = 1 and u.country in ('US','CA') group by u.id, u.name having count(o.id) > 3 order by orders desc limit 10

The formatter returns 13 lines:

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.active = 1
  AND u.country IN ('US','CA')
GROUP BY u.id,
   u.name
HAVING COUNT(o.id) > 3
ORDER BY orders DESC
LIMIT 10

The two top-level commas after SELECT put u.name and COUNT(o.id) AS orders on their own lines, while the comma inside ('US','CA') sits inside parentheses and stays put. left join matches the two-word marker LEFT JOIN before the bare JOIN, so the whole phrase opens the line, and on drops to an indented ON beneath it. The literals 'US' and 'CA' were protected, so their case is untouched. Comma continuation lines are indented three spaces rather than two, because the space after each comma survives the line break.

Assumptions and limits

  • Comments are not recognized. Because all lines are joined into one, a -- comment can swallow code that followed it. select a -- the id with , b from t on the next line comes out as SELECT a -- the id , and then b, which a database reads as column a aliased to b. Remove line comments first.
  • No nesting. A subquery’s SELECT, FROM and WHERE start at the left margin like the outer query’s, and a window function’s ORDER BY breaks out of its OVER (...).
  • Every AND is a condition. The AND in BETWEEN 1 AND 5 also moves to its own line.
  • A fixed keyword list. WITH, OVER and PARTITION keep the case you typed, while an unquoted column named count or end is capitalized.
  • Generic quoting only. PostgreSQL dollar-quoted bodies and SQL Server square-bracket names are not protected.

How to use the result

  • Read the left margin first. SELECT, FROM, the joins, WHERE, GROUP BY: top to bottom, it tells you whether the query does what the ticket says before you read any detail.
  • Check every join has its ON. An indented ON under each join line is the quickest way to spot an accidental cross join.
  • Watch mixed AND and OR. At the same indentation they still evaluate AND first, so add parentheses if you meant otherwise.
  • Paste the formatted query into reviews. One clause per line makes later diffs show the clause that changed.
  • Execute the original. For queries with comments or dialect-specific syntax, run what you wrote and use the formatted copy for reading.

How it works

  • Each major clause on its own line, standard keywords uppercased.
  • Top-level commas and AND / OR / ON conditions get their own indented lines.
  • Leaves string literals and quoted identifiers untouched.
  • Lightweight and dialect-agnostic: readability, not full parsing.

Frequently asked questions

What does the SQL formatter actually do?

It applies a fixed set of text rules. It protects quoted strings and identifiers, collapses all whitespace, uppercases 50 standard keywords, and starts a new line at every top-level comma. Each of 26 clause markers, such as SELECT, FROM, the JOIN variants, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, UNION, VALUES and SET, begins a new line at the left margin, and AND, OR and ON go on indented lines beneath their clause. The result is the same query laid out so its structure can be scanned.

Does formatting change what my query does?

For ordinary SQL, no. It changes only whitespace and the case of keywords, and SQL keywords are case-insensitive, while string literals and quoted identifiers are restored exactly as typed. The exception is comments. The formatter does not recognize them, and because it joins every line into one, code that followed a double-dash comment on the next line can end up inside that comment. Remove line comments before formatting, or run your original query and keep the formatted copy for reading.

Is this a full SQL parser?

No, and that is a deliberate trade-off. It is a lightweight, dialect-agnostic formatter built from pattern rules, which handles everyday SELECT, INSERT, UPDATE and DELETE statements well. It does not track nesting, so a subquery starts its clauses at the left margin, a window function splits at its ORDER BY, and the AND inside BETWEEN 1 AND 5 moves to its own line. For deeply nested or vendor-specific SQL, a dialect-aware formatter in your IDE or database client will do better.

Why uppercase SQL keywords?

It is a long-standing convention that separates the language, words like SELECT, WHERE and JOIN, from your own table and column names, so a reviewer can see the shape of a query at a glance. It is purely stylistic, because SQL keywords are case-insensitive in every major database. If your team prefers lowercase keywords, that works just as well; what matters is that everyone writes the same way, so diffs show real changes rather than casing noise.

Which words get uppercased?

A fixed list of 50 keywords, covering clauses, joins, set operators, comparisons such as IN, IS, LIKE and BETWEEN, the aggregates COUNT, SUM, AVG, MIN and MAX, CASE expressions, and ASC and DESC. Words outside the list, such as WITH, OVER, PARTITION or CREATE, keep the case you typed. Matching is by whole word, so an unquoted column named count or end is capitalized too, while anything inside quotes, such as a column written as "order", is never changed.