Skip to content
Tools

SQL Formatter

Format, beautify and organize SQL queries instantly with support for multiple SQL dialects. Everything runs locally in your browser.

Visible pane

SQL

0 chars

Loading editor…

Waiting for SQL

ANSI SQL

What is SQL formatting?

SQL ignores whitespace. A query written as one 400-character line and the same query spread over twenty lines are identical to the database — it parses both into exactly the same plan. Formatting is entirely for the reader. It takes a query whose structure is buried in a wall of text and puts that structure back on the screen: one clause per line, one column per line, nested queries indented inside their parentheses.

The same query, before and after
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.plan='pro' group by u.id,u.name having count(o.id)>2 order by orders desc; SELECT  u.id,  u.name,  COUNT(o.id) AS ordersFROM users uLEFT JOIN orders o ON o.user_id = u.idWHERE u.active = 1  AND u.plan = 'pro'GROUP BY u.id, u.nameHAVING COUNT(o.id) > 2ORDER BY orders DESC;

Nothing changed except whitespace and the casing of keywords. The second version runs the same, returns the same rows and takes the same time — but you can see in one pass that there is a left join, two filters and a group, and you could point at the line you wanted to change. The freedom runs both ways: the SQL minifier collapses the formatted version back to a single line for embedding in code, and the database still reads it identically.

Everything here runs in your browser. The queries people paste into a formatter carry table names, column names and often real values, so nothing is uploaded, stored or logged.

Why format SQL queries?

Because unformatted SQL hides exactly the things that go wrong with it. Almost every SQL bug is a structural one — a join condition that got attached to the wrong table, a filter that ended up in the WHERE instead of the ON, a parenthesis one position out — and all of them are invisible in a single line and obvious once the structure is on separate lines.

  • Reviews stop being archaeology. A reviewer can see which clauses exist and which columns are selected without rebuilding the query in their head first.
  • Diffs shrink to the actual change. With one column per line, adding a column is a one-line diff, whether in a pull request or a diff checker. On a single-line query, it is a change to the whole query and nobody can see what moved.
  • Copied queries become readable.SQL pulled out of an application log, an ORM’s debug output or a slow-query report arrives as one long line. Formatting is the first step to understanding it.
  • Dangerous statements announce themselves. A DELETE with no WHERE is easy to miss in a paragraph of text and hard to miss on its own line — and this tool warns about it besides.
  • Teams stop arguing about style. One agreed set of options, applied by a tool, ends the discussion about where the commas go.
  • Learning gets faster. Clause order is one of the first things to internalise about SQL, and seeing every query laid out in that order teaches it far quicker than reading prose about it.

Supported SQL dialects

“Standard SQL” is aspirational. Every engine extends the grammar, and the extensions that matter most to a formatter are the ones that change what a character means — because reading a quote wrongly turns a string into a name, or a name into a string, and everything after it is wrong too.

The same idea, four ways to quote a name
SELECT `order` FROM `user`;     -- MySQL, MariaDB, BigQuerySELECT "order" FROM "user";     -- PostgreSQL, Oracle, SQLiteSELECT [order] FROM [user];     -- SQL ServerSELECT "order" FROM "user";     -- ANSI SQL

Pick an engine from the options, or leave detection on and let the query speak for itself. Detection scores markers rather than trusting any single one: a query with nothing distinctive in it stays ANSI instead of being guessed at.

MySQL

Names are wrapped in backticks, # starts a comment as well as --, a backslash escapes inside a string literal, and LIMIT takes an offset before the count. AUTO_INCREMENT and ENGINE=InnoDB are the giveaways detection looks for.

PostgreSQL

Names are wrapped in double quotes, :: casts, $$ … $$ quotes a whole function body without escaping anything inside it, and RETURNING gives a write statement a result set. SERIAL and JSONB are the strongest signals.

SQL Server

Names go in square brackets, which nothing else does — so a [bracketed] name is close to proof on its own. Add SELECT TOP, N'unicode strings', @variables, GETDATE() and batches separated by GO.

Oracle

VARCHAR2 rather than VARCHAR, NUMBER rather than NUMERIC, SYSDATE rather than NOW(), NVL rather than COALESCE, ROWNUM rather than LIMIT, and SELECT … FROM DUAL when there is no table to read from.

SQLite

A small dialect with two unmistakable markers: AUTOINCREMENT spelled without the underscore MySQL uses, and PRAGMA statements. INTEGER PRIMARY KEY and WITHOUT ROWID point the same way.

MariaDB

MySQL's fork, and close enough that a MariaDB-only marker has to win outright before it is chosen — otherwise every MySQL dump with a backtick in it would be labelled on a coin flip. ENGINE=Aria and PERSISTENT columns are the honest signals.

Snowflake

QUALIFY filters on a window function without a subquery, VARIANT holds semi-structured data, LATERAL FLATTEN unrolls it, and IFF is the two-branch conditional. All four are rare enough elsewhere to be conclusive.

BigQuery

Fully qualified `project.dataset.table` names in backticks, INT64 and FLOAT64 instead of INT and DOUBLE, STRUCT<> and ARRAY<> types, SAFE_CAST for casts that return NULL rather than failing, and UNNEST for arrays.

Formatting features

Keyword formatting

Keywords, types and built-in function names can be uppercased, lowercased or capitalised. Uppercase is the long-standing convention and the default: it separates the words SQL owns from the words your schema owns, which is most of what makes a query skimmable. Identifiers are a separate setting and default to being left exactly as written — and a quoted name is never recased at all, since quoting it is precisely how you asked for its case to be kept.

Indentation

Two spaces, four spaces or tabs, applied to clause contents, nested queries and table definitions. A subquery is indented inside its parentheses so its own clauses read as a query in their own right, and the closing parenthesis returns to the level of the line that opened it.

A subquery keeps its own shape
SELECT nameFROM usersWHERE id IN (  SELECT user_id  FROM orders  WHERE total > 500);

Clause alignment

Turn on align clauses for the river style, where the clause keywords share a right edge and their contents hang one column past it. Some people read a query by scanning that keyword column; for them the river is much faster than a left-aligned list.

The river style
  SELECT         u.id,         u.name    FROM users u    JOIN orders o ON o.user_id = u.id   WHERE u.active = 1         AND o.total > 10GROUP BY u.idORDER BY u.name;

Syntax highlighting

Keywords, types, functions, table names, column names, strings, numbers, parameters and comments each get their own treatment, in both panels and in both light and dark themes. Table names are picked out from column names by position — a name after FROM, JOIN, INTO, UPDATE or TABLE is a table — so the shape of a join chain is visible without reading it.

Validation

Every issue comes with a line, a column, a caret pointing at the exact character and something to do about it. What it checks is deliberately bounded to what can be established from the text with certainty:

  • Unterminated strings, comments and quoted names. The most destructive class of error, because everything after the opening quote is being read as something it is not.
  • Unbalanced parentheses. Reported against the one that has no partner, not against the end of the query.
  • Trailing and doubled commas, and a SELECT with no columns at all.
  • UPDATE or DELETE with no WHERE, which is valid SQL and applies to every row in the table.
  • A SELECT whose clauses imply a table it never names. SELECT 1 is fine; SELECT u.id WHERE … is not.
  • Mistyped keywords, allowing one edit including a swap of neighbouring letters — which is how FORM happens.

It is a linter, not a database. It cannot tell you that a table does not exist or that a column is misspelled, and it does not pretend to.

Common SQL statements

Seven statements cover almost everything anyone writes by hand. Each one has a shape, and formatting exists to make that shape visible.

SELECT

Reads rows. The clause order is fixed — SELECT, FROM, JOIN, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT — and the formatter gives each one a line, which makes a missing or misplaced clause obvious at a glance.

INSERT

Adds rows. The column list stays beside the table name; several VALUES tuples get a line each, so a row with the wrong number of values lines up visibly short against its neighbours.

UPDATE

Changes rows in place. Each assignment in the SET clause gets its own line, and the tool warns when there is no WHERE — an UPDATE without one rewrites every row in the table.

DELETE

Removes rows. Carries the same missing-WHERE warning as UPDATE, and for the same reason: the statement is valid SQL, so nothing but a warning stands between a typo and an empty table.

CREATE

Defines tables, views, indexes and procedures. A table definition gets one column per line with its constraints kept alongside it, so ON DELETE CASCADE stays attached to the foreign key it belongs to.

ALTER

Changes an existing definition — adding a column, adding a constraint, renaming something. Usually written as a run of short statements, which the formatter separates with a blank line each.

DROP

Removes an object entirely. Short, irreversible, and worth reading twice before running: formatting will not save you from dropping the wrong table, but it will at least make the name easy to see.

Best practices for writing SQL

Indent to show nesting, not to decorate

Indentation should mean one thing: this is inside that. A subquery indented inside its parentheses, a column indented under the clause that selects it, a procedure body indented inside its BEGIN. Indentation used for anything else — lining up equals signs, centring things — breaks the moment a name gets longer.

Alias tables, and alias them consistently

A short alias used everywhere beats a long table name repeated everywhere, and a consistent alias beats a short one. If users is u in one query it should be u in all of them. Always qualify columns once there is more than one table in play: id in a three-way join is a question, and u.id is an answer.

Qualified columns and consistent aliases
SELECT  u.id,  u.email,  o.totalFROM users uINNER JOIN orders o ON o.user_id = u.idWHERE u.active = 1;

Give every join its own line, and its condition beside it

A join is two facts — which table, and how it connects — and they belong together on one line. Read down the left edge and you have the whole join chain. Put the filtering conditions in the WHERE and the joining conditions in the ON: mixing them is legal, changes the result for outer joins, and is the single most common cause of a query that returns nearly the right rows.

Name things for the person who reads them next

Plural table names or singular ones, snake_case or camelCase — it matters far less which you pick than that you pick one. Avoid reserved words as names: a column called order or user has to be quoted forever afterwards, in every query, by every person who touches it. Name a computed column for what it means — order_count, not c.

Optimise for reading

A query is written once and read for years. Prefer an explicit column list to SELECT *, so the query keeps returning the same shape after somebody adds a column. Break a query that has grown past comprehension into CTEs with names that say what each step produces. Leave a comment for the why — the business rule behind an odd-looking filter — and let the formatting carry the what.

Frequently asked questions

Is this SQL formatter free?

Yes. Formatting, minifying, validating, uploading, downloading and every option are free, with no account, no sign-up and no cap on how many queries you format.

Is my SQL uploaded anywhere?

No. The query is tokenised and formatted by JavaScript running in your browser. Nothing is sent to a server, nothing is stored and nothing is logged. You can disconnect from the network after the page loads and the tool keeps working — which matters, because the queries people paste into formatters routinely contain table names, column names and sometimes real values from production.

Does formatting change what my query does?

No. Formatting only changes whitespace and, if you ask it to, the casing of keywords and unquoted identifiers. String literals, quoted names, numbers, comments and bind parameters are reproduced character for character. SQL is insensitive to whitespace and to keyword case, so the reformatted query is the same query. The one option that can alter the text beyond whitespace is turning comments off, and it is off by default.

Which SQL dialects are supported?

ANSI SQL, MySQL, MariaDB, PostgreSQL, Microsoft SQL Server, Oracle, SQLite, Snowflake and BigQuery. The dialect changes which words count as keywords and types, and — more importantly — how quoting and comments are read: backticks are names on MySQL and BigQuery, square brackets are names on SQL Server, dollar-quoted bodies are strings on PostgreSQL, and # starts a comment only on MySQL and MariaDB.

How does dialect detection work?

Each dialect has a list of markers and the one with the most evidence wins. A backtick, AUTO_INCREMENT and ENGINE=InnoDB together mean MySQL; SERIAL and JSONB mean PostgreSQL; square brackets, SELECT TOP and GETDATE() mean SQL Server; FROM DUAL and SYSDATE mean Oracle. A query with no distinguishing marks is left as ANSI rather than guessed at, because guessing wrong changes how quotes are read.

Can I format stored procedures?

Yes. BEGIN … END blocks, IF … THEN … ELSE … END IF, loops and DECLARE statements are all indented as blocks, and a semicolon inside a procedure body ends the statement without ending the block it sits in. Nested blocks indent from wherever they opened rather than from the left margin.

Can I minify SQL?

Yes. Minifying collapses the query to a single line with the smallest spacing that still parses, and removes comments — which is a correctness requirement rather than a size saving, because a -- comment with no newline after it would comment out the rest of the statement. Two minus signs that would otherwise become a comment marker are kept apart.

Can I validate SQL syntax?

It checks the things that can be established with certainty from the text: unterminated strings, comments and quoted names, unbalanced parentheses, trailing and doubled commas, a SELECT with no columns, a missing final semicolon, an UPDATE or DELETE with no WHERE, a SELECT whose clauses imply a table it never names, and mistyped keywords. It is a linter, not a database — it cannot know whether a table exists or a column is spelled right.

Why does it warn about DELETE without WHERE?

Because a DELETE or UPDATE with no WHERE clause applies to every row in the table, and that is almost never what was intended when it happens by accident. The statement is perfectly valid SQL, so it is reported as a warning rather than an error, with the suggestion to run it as a SELECT first to see exactly which rows it would touch.

How does it catch a mistyped keyword?

By comparing the word against the keywords it could plausibly be, allowing one edit — including a swap of two neighbouring letters, which is how FORM becomes the most common SQL typo there is. The check is deliberately narrow about where it applies: `orders` is one letter away from ORDER and is a table on half the databases in the world, so a name is only questioned in a position where a name cannot legally go.

Can I upload a .sql file?

Yes. Use the upload button or drag a .sql file anywhere onto the tool. The file name is shown above the input panel and is reused when you download the result. Files are read as UTF-8, so accented and non-Latin text in comments and string literals survives intact.

How large a script can it handle?

Up to about 10 MB of text. Formatting is debounced so typing stays responsive, and the scanner makes a single pass with no recursion, so a large script cannot overflow anything. The editor only highlights what is on screen, which is what keeps scrolling through a multi-megabyte dump smooth. Anything larger than 10 MB genuinely belongs in a script rather than a browser tab.

What is the difference between leading and trailing commas?

Where the comma sits when a list breaks across lines. Trailing puts it at the end of each line, which is what most people write. Leading puts it at the start of the next line, which makes it obvious when one is missing and lets you comment out a column without breaking the line above it. Both produce identical SQL.

What does align clauses do?

It switches to the river style, where the clause keywords in a block share a right edge and the contents hang one column past them — SELECT, FROM and WHERE line up on their last letter rather than their first. It suits people who read queries by scanning the keyword column. It is off by default because the indented style is what most codebases use.

Why did my SELECT list break onto separate lines?

A select list with more than one item always gets a line each: it is the part of a query that changes most often, and one column per line makes a diff show exactly which one moved. Lists elsewhere — GROUP BY, ORDER BY, a FROM with several tables — stay on one line until they would overrun about 80 characters, so a short query stays short.

Are comments preserved?

Yes, by default. A comment written at the end of a line stays at the end of that line; a comment on its own line keeps a line of its own; and the interior of a multi-line block comment is left exactly as written. You can turn comments off in the options, which drops them from the output entirely.

Can I search inside a large query?

Yes. The search button, or Ctrl/Cmd+F, opens a search over the input with every match highlighted, a match counter, and previous and next buttons to step through them. It searches whatever is in the panel — keywords, table names, column names, function names or literal values. Escape closes it.

Are there keyboard shortcuts?

Ctrl/Cmd+Enter formats, Ctrl/Cmd+Shift+M minifies, Ctrl/Cmd+Shift+C copies the output, Ctrl/Cmd+Shift+D downloads it, Ctrl/Cmd+Shift+L loads another sample, Ctrl/Cmd+Shift+Delete clears the input, and Ctrl/Cmd+F opens the search. Escape closes the search.

Can I download the result as a PDF?

Yes. The download menu offers a .sql file, a .txt file, and a PDF produced through your browser's own print dialog — choose “Save as PDF” as the destination. Going through the browser rather than bundling a PDF library keeps the page small and keeps your query out of any third-party code.

Does it work offline?

Once the page has loaded, yes. Everything runs locally, so you can disconnect and keep formatting. A connection is only needed to load the page the first time.

Popular tools

↑ ↓NavigateOpenEscClose