Skip to content

SQL Formatter & Beautifier

Format SQL queries with dialect-aware parsing for MySQL, PostgreSQL, T-SQL, PL/SQL, and standard SQL.

In your browseryour files never leave your device.

Learn more
⌘⇧F format
Formatted SQL will appear here…

About this tool

SQL is a 50-year-old language with vendor extensions that diverged decades ago. A standard PostgreSQL CTE with RECURSIVE is not valid in older MySQL; a MERGE statement is T-SQL and Oracle PL/SQL with different syntax in each; date and string functions are deeply non-portable (NOW() vs CURRENT_TIMESTAMP vs SYSDATE, CONCAT() vs || vs +, the list goes on). This formatter uses the sql-formatter library, which understands the keyword sets and reserved words for the major dialects, so a Postgres-specific RETURNING clause does not get mis-broken across lines like an unknown identifier would. Indentation is consistent. SELECT lists, JOIN conditions, WHERE predicates, and HAVING clauses all get their own lines at the right depth. Output is suitable for code review, pull requests, or just reading a 200-line analytics query without going cross-eyed.

How to sql formatter & beautifier

  1. Paste your SQL

    A single SELECT, a multi-statement script, a stored procedure body, an ORM-generated WTF — the formatter handles whatever you give it. Empty input shows nothing; one keyword shows that keyword properly cased; full queries get full structure.

  2. Pick the dialect

    If you know your target database, pick its dialect for the most accurate formatting. If you do not, the generic SQL mode handles ANSI-standard queries (which is most of what people write day-to-day). Switching dialects re-runs the formatter on the current input, so you can compare how the same query looks under different vendor rules.

  3. Read the formatted output

    Indentation reflects the query structure. JOIN, WHERE, GROUP BY, HAVING, ORDER BY each start on their own line at the right level. Comma-separated lists in SELECT and GROUP BY get column-per-line layout for long lists, which makes diffs in version control much cleaner.

  4. Copy and ship it

    One click sends the formatted query to your clipboard. Paste into your migration file, your dashboard, your PR description, or your ORM's raw-query escape hatch. Reading SQL in a PR description versus reading it minified in a code review tool is the difference between catching a bug and approving it.

Why use this tool

BI queries arrive in my inbox as 400 characters on one line, mostly because someone wrote them in a Looker SQL block or a Mode notebook where horizontal scrolling is the default. Pasting them in here and getting a structured view is the first step in figuring out what they actually do. The second case is generating SQL from an ORM and wanting to see what got emitted before sending it to production — Prisma, Drizzle, SQLAlchemy, and Active Record all dump compressed SQL when you turn on query logging, and reading a 50-table JOIN without formatting is borderline impossible. The third case is sanity-checking a junior engineer's PR. A formatted query exposes the JOIN order, the missing WHERE clause that turns it into a cross join, and the GROUP BY column that does not match the SELECT. Bad SQL hides in dense formatting; structure forces it into the open. The fourth is preparing a query for a runbook or a wiki where someone else will have to read it months later — formatted SQL is documentation-quality, raw SQL is a write-once disaster.

Features

Five dialect modes

Standard SQL, MySQL, PostgreSQL, T-SQL (SQL Server), and PL/SQL (Oracle). Each mode knows the keyword set and reserved words for that dialect, so vendor-specific syntax — Postgres LATERAL joins, T-SQL CROSS APPLY, MySQL backtick-quoted identifiers, Oracle CONNECT BY hierarchical queries — gets correctly formatted instead of mangled. If you pick the wrong dialect, the formatter usually still works but vendor keywords might get treated as identifiers and laid out incorrectly.

Consistent keyword case

Output uses uppercase for SQL keywords (SELECT, FROM, WHERE, JOIN, GROUP BY, ORDER BY) and preserves identifier case from the input. This is the convention in 80% of style guides and reads cleanly in code review even when the source was lowercase chaos. The clear visual distinction between keywords and identifiers also makes it easier to spot when a typo turned a keyword into an identifier (e.g. "FORM" instead of "FROM").

Live formatting with debounce

Output updates as you type or paste, with a small debounce so the page does not lock up on a 5,000-character query. No "Format" button to press. The debounce is set to feel instant for short queries and avoid stuttering on long ones; for queries above 10,000 characters the formatting takes a noticeable pause but still completes.

Error reporting for malformed input

If the parser cannot make sense of your query — unclosed quote, missing parenthesis, syntax error from a misspelled keyword — you get a clear error message rather than silently mangled output. The formatter does not execute the query, so it cannot catch semantic errors (a non-existent table, a misnamed column, a JOIN on incompatible types), but structural problems get flagged. Often the error position is a useful hint about where to look.

Privacy & security

This tool runs entirely in your browser. Your files are never uploaded to a server — every step of the process (reading, transforming, downloading) happens on your device using JavaScript and the Web APIs. You can verify this in your browser's network tab: clicking the tool's main action triggers zero requests to our servers. The page itself is served over HTTPS, but once it loads, your data stays put. No accounts, no tracking of file contents, no scanning your inputs.

Frequently asked questions

Does this run the query or validate it against a real database?
No. It formats only. The parser knows SQL syntax but it has no schema, no tables, no data. So a typo in a table name, a column that does not exist, a JOIN on the wrong key — none of those get caught here. For semantic validation you need to run the query against the actual database, ideally a non-production one. EXPLAIN ANALYZE on the real database tells you not just whether the query works but how fast.
Why does my Postgres-specific syntax break in MySQL mode?
Postgres has features MySQL does not — LATERAL joins, FILTER on aggregates, GENERATED ALWAYS columns, native JSON path operators (->), DISTINCT ON, full window function support. If you paste a query that uses these and pick MySQL as the dialect, the parser will choke because those keywords are not valid MySQL syntax. Pick PostgreSQL mode and they format correctly. The reverse is also true — MySQL backtick identifiers (`column_name`) are not standard SQL and Postgres mode treats them as syntax errors.
Will the formatter rewrite my query for performance?
No — only the layout changes. Reorganizing FROM clauses, swapping IN for EXISTS, hoisting a subquery into a CTE, pushing a WHERE down into a JOIN, or any other rewrite that could change the execution plan is out of scope. This is a beautifier, not an optimizer. EXPLAIN ANALYZE on the real database is how you make those decisions. There are query optimizers (pgFormatter, EverSQL, EXPLAIN.dalibo.com for Postgres specifically) but they require connection to a real database with real statistics.
Does it handle stored procedure bodies?
Mostly. The parser understands CREATE PROCEDURE / FUNCTION blocks, IF / THEN / ELSE structures, and DECLARE statements for the dialects that support them (T-SQL and PL/SQL particularly). Very vendor-specific control flow (Oracle's LOOP / CONTINUE WHEN, T-SQL's TRY / CATCH, PostgreSQL's PERFORM) can occasionally trip the parser; fall back to a real IDE (DataGrip, DBeaver, SQL Server Management Studio) for those. The formatter is best at SELECT-style data queries; procedural code is a secondary use case.
Privacy when pasting production queries?
Formatting runs in your browser. Your queries are not transmitted. Important when the query contains real schema names, sample data values that should not leak, or hard-coded credentials that should not have been in the query string in the first place. Open DevTools, paste a query, watch the Network tab — zero requests.
What about identifiers with spaces or reserved words?
The formatter respects whatever quoting style you used: backticks for MySQL, double quotes for ANSI/Postgres, square brackets for T-SQL. It does not normalize between them — that would change query semantics on systems where the quoting style matters. So `my column` stays as `my column` in MySQL mode, and "my column" stays as "my column" in Postgres mode.
Can it format a multi-statement script?
Yes. The parser handles semicolon-separated statements and formats each independently. So a migration file with five CREATE TABLE statements and a few INSERT statements all get formatted together, with appropriate spacing between. Useful for cleaning up generated migrations or seed scripts.
Why does my INSERT statement look ugly?
INSERT INTO ... VALUES (...) with long value lists is structurally hard to format well — each value list is one row of data and there is no natural place to indent. The formatter typically puts each VALUES tuple on its own line, which is the cleanest layout for human reading. If you have hundreds of value rows, consider using COPY (Postgres) or LOAD DATA INFILE (MySQL) instead — they handle bulk inserts much faster.