SQL Formatter & Beautifier

SQL Input
Formatted SQL

How to Format SQL Online

Paste your SQL query into the input box on the left. Select your database dialect and formatting preferences from the options bar, then click Format SQL — or just start typing and the formatter runs automatically. The output panel shows clean, readable SQL with proper indentation and consistent keyword casing, ready to copy back into your editor or query tool.

Supported SQL Dialects

This formatter supports MySQL, PostgreSQL, SQLite, T-SQL (SQL Server), Standard SQL, and BigQuery. Selecting the correct dialect ensures dialect-specific keywords and functions are recognized and formatted correctly. For example, PostgreSQL supports :: casting syntax and RETURNING clauses, while T-SQL uses TOP instead of LIMIT.

SQL Formatting Best Practices

PracticeWhy It Matters
Uppercase keywordsVisually separates SQL keywords from identifiers and values, improving scan-ability
One clause per lineSELECT, FROM, WHERE, JOIN each on their own line makes diffs cleaner and logic easier to follow
Consistent indentationNested subqueries and conditions are much easier to trace with 2 or 4 space indentation
Alias with ASExplicit AS keyword makes column and table aliases unambiguous and self-documenting
Avoid SELECT *Explicit column lists prevent unexpected columns in results and improve query performance

What Formatting Actually Changes

A formatter rewrites whitespace and keyword casing. It never changes what a query does — the parse tree is identical before and after — so it is safe to run on production SQL. Here is the transformation on a typical unformatted query.

Before
select u.id,u.email,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'
and u.status='active' group by u.id,u.email
having count(o.id)>5 order by orders desc limit 20;
After
SELECT
  u.id,
  u.email,
  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'
  AND u.status = 'active'
GROUP BY
  u.id,
  u.email
HAVING
  count(o.id) > 5
ORDER BY
  orders DESC
LIMIT
  20;

Each clause keyword sits on its own line with its operands indented beneath it, so the shape of the query is visible before you read a single identifier. Note that count stays lowercase: the "uppercase keywords" option applies to SQL keywords, not function names, which keeps your own naming untouched.

The second version makes the join condition, the two filters, and the aggregate threshold individually visible. In review, that is the difference between spotting a missing AND and merging it.

Why Formatted SQL Matters in Review

Three concrete payoffs, beyond aesthetics.

Diffs become meaningful. When a query sits on one long line, changing a single condition marks the entire line as modified and the reviewer must compare two walls of text character by character. With one clause per line, the diff highlights exactly the clause that changed.

Missing join conditions become visible. A LEFT JOIN whose ON clause was forgotten produces a Cartesian product — a query that works fine against a small development dataset and takes down production. Indented and aligned, a join without its condition is obvious on sight.

Operator precedence stops hiding. WHERE a = 1 OR b = 2 AND c = 3 does not do what it appears to, because AND binds tighter than OR. Formatting puts each condition on its own line and makes the grouping — and the missing parentheses — apparent.

Dialect Differences That Matter

Selecting the right dialect matters because these constructs are not portable.

TaskPostgreSQLMySQLT-SQL
Limit rowsLIMIT 10LIMIT 10TOP 10
Quote an identifier"column"`column`[column]
String concatenation||CONCAT()+
Current timeNOW()NOW()GETDATE()
Cast a valuevalue::intCAST(value AS SIGNED)CAST(value AS INT)
UpsertON CONFLICTON DUPLICATE KEYMERGE

Choosing the wrong dialect usually shows up as a backtick-quoted identifier being treated as a string, or a :: cast being split across lines. If the formatted output looks structurally wrong, check the dialect selector before anything else.

Reading an Unfamiliar Query

Formatting is the first step; here is a reliable order for the rest.

  1. Start at FROM, not SELECT. SQL executes FROM and JOIN first, then WHERE, GROUP BY, HAVING, SELECT, and finally ORDER BY. Reading in execution order rather than written order makes the logic follow naturally — and explains why a column alias defined in SELECT cannot be used in WHERE.
  2. Identify the grain. Determine what one row of the result represents. If a join multiplies rows, every downstream aggregate is inflated — the most common cause of "our numbers are double."
  3. Read the CTEs top down. A well-written WITH chain reads like a pipeline, each step named. If a CTE is used only once and is trivial, it is often clearer inlined.
  4. Check NULL handling. NULL = NULL is not true, and a NOT IN against a subquery containing a single NULL returns no rows at all. Use NOT EXISTS instead.
Formatting is not sanitising. Making a query readable does nothing about SQL injection. Concatenating user input into a string is unsafe no matter how neatly it is laid out — always use parameterised queries or prepared statements.

Working Formatting Into Your Workflow

Ad-hoc formatting helps most when it is not ad-hoc. Adopt one style per repository and enforce it, so diffs never contain pure whitespace noise. Most teams settle on uppercase keywords, lowercase identifiers, two-space indentation, and leading commas or trailing commas chosen once and never revisited.

Format migrations before committing them, since a migration is read far more often than it is written — usually at an awkward moment, when someone is working out what changed. The same goes for queries embedded in application code and for the SQL that lives in analytics configs; if those configs are YAML, our YAML to JSON converter helps verify the nesting is right. For queries executed by scheduled reporting jobs, our cron expression generator confirms the schedule fires when you expect.

Query performance still a mystery after formatting? Formatting reveals a query's logic but not its cost. Managed Postgres platforms such as Neon and Supabase expose per-query statistics and plan analysis, which is what tells you whether that LEFT JOIN is doing a sequential scan. These are affiliate links — they cost you nothing and help keep these tools free.

Frequently Asked Questions

Does formatting change what my query returns?
No. Only whitespace and keyword casing change. The query is semantically identical, so results and execution plan are unaffected.
Is my SQL sent to a server?
No. Formatting runs entirely in your browser, so it is safe to paste queries containing real table and column names.
Why does uppercasing keywords matter?
SQL keywords are case-insensitive, so it is purely for readability — uppercase keywords let your eye separate the language from your schema at a glance. What matters most is consistency across the codebase.
Can it format stored procedures and multiple statements?
Multiple statements separated by semicolons format fine. Procedural blocks such as PL/pgSQL or T-SQL control flow are formatted on a best-effort basis, since they extend well beyond standard SQL.
My comments moved. Is that expected?
Yes. A comment is attached to a position in the token stream, so when the surrounding statement is re-laid-out the comment moves with it. Review comment placement after formatting a heavily annotated query.