Skip to content

SQL Query Formatter

Paste a query that arrived on one long line and get it back with SELECT, FROM, WHERE and the other main clauses each starting a new line, and keywords in the case you choose.

Runs in your browserFree, no sign-upLast reviewed

Settings

Results update automatically as you type.

Formatted SQL

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
GROUP BY u.id
ORDER BY orders DESC
LIMIT 10

Quick answers

How do I format a SQL query that is all on one line?
Paste it into the SQL query box. The formatter starts a new line at SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, each JOIN and ON, indents AND and OR, and breaks after each comma. The default sample goes from one line to eleven.
Should SQL keywords be uppercase?
It is a convention, not a rule. SQL keywords are case-insensitive, so select and SELECT run identically in every major database. Uppercase is the traditional style because it separates the language from your table and column names at a glance. Some style guides prefer lowercase. Pick one and apply it consistently.
Does formatting change what a query does?
Changing whitespace and keyword case outside quotes does not. This tool, however, also applies its rules inside quoted strings and comments: 'salt and pepper, please' comes back with AND in capitals and line breaks inside the value. Review any query that contains string literals or comments before using the output.
Which SQL dialects does it work with?
Any of them for ordinary statements, because it only looks for common keywords shared by MySQL, PostgreSQL, SQLite, SQL Server and Oracle. It has no dialect setting and no knowledge of dialect-specific syntax, so words such as TOP, RETURNING, ILIKE or QUALIFY are left exactly as typed.
Does it change table or column names?
Not on purpose. Identifiers keep their original case. The exception is a name that is itself one of the recognised keywords: a column called count, set, end or values will be recased, and some will be pushed onto a new line, because the tool cannot tell a name from a keyword.

About SQL Formatter

This SQL query formatter is built for the everyday case: a SELECT, INSERT, UPDATE or DELETE copied out of a log, an ORM debug line or a chat message as one unbroken line. It collapses the whitespace, puts every main clause on a new line, indents AND and OR conditions by two spaces, breaks after each comma, and sets recognised keywords to UPPERCASE or lowercase. Table and column names are left as typed. It works by pattern matching and does not parse SQL, which keeps it fast and dialect-neutral but brings real limits: it does not indent subqueries, and it does not protect the inside of quoted strings or comments. Check the output before running it if your query contains either.

Before and after: formatted SQL examples

Each result is this formatter's exact output with Keyword case set to UPPERCASE unless stated. Line breaks are shown as slashes; AND, OR and items after a comma are indented two spaces in the real output.

Filter with AND and OR

SELECT * FROM orders WHERE status = 'paid' AND total > 100 OR priority = 1

SELECT * / FROM orders / WHERE status = 'paid' / AND total > 100 / OR priority = 1

Join with a sort

select p.name, c.name from products p join categories c on c.id = p.category_id where c.active = 1 and p.price > 20 order by p.name

SELECT p.name, / c.name / FROM products p / JOIN categories c / ON c.id = p.category_id / WHERE c.active = 1 / AND p.price > 20 / ORDER BY p.name

Grouping with HAVING

select department, avg(salary) from employees group by department having avg(salary) > 50000 order by department asc

SELECT department, / AVG(salary) / FROM employees / GROUP BY department / HAVING AVG(salary) > 50000 / ORDER BY department ASC

UPDATE with two assignments

update users set active = 0, updated_at = now() where last_login < '2025-01-01'

UPDATE users / SET active = 0, / updated_at = now() / WHERE last_login < '2025-01-01'

now() is not on the keyword list, so it keeps the case it was typed in.

UNION ALL

select id from a union all select id from b

SELECT id / FROM a / UNION ALL / SELECT id / FROM b

The default sample, with a LEFT JOIN

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 group by u.id order by orders desc limit 10

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 / GROUP BY u.id / ORDER BY orders DESC / LIMIT 10

LEFT lands on a line of its own above JOIN. The same happens with RIGHT, INNER and CROSS joins. The query is still valid.

Lowercase keywords

Select Id From Users Where Id Is Null, with Keyword case set to lowercase

select Id / from Users / where Id is null

Keywords are lowered; the identifiers Id and Users keep their capitals.

A string that contains a keyword and a comma

select * from t where note = 'salt and pepper, please'

SELECT * / FROM t / WHERE note = 'salt / AND pepper, / please'

The quoted value has been altered. This is the main case where the output must not be run as it stands.

Which keywords the formatter recognises and what it does with each

Anything not in this table is treated as an ordinary word and left untouched.

KeywordsCase changed?Layout
SELECT, FROM, WHERE, GROUP BY, ORDER BY, HAVING, LIMIT, OFFSETYesStarts a new line
INSERT INTO, VALUES, UPDATE, SETYesStarts a new line
DELETE FROMYesAt the very start of the input FROM drops to the line below DELETE; after an earlier statement DELETE FROM starts a new line and stays together
UNION, UNION ALLYesStarts a new line
JOIN, ONYesEach starts a new line
LEFT JOIN, RIGHT JOIN, INNER JOIN, OUTER JOIN, CROSS JOINYesNew line before the first word, and another before JOIN
AND, ORYesNew line, indented two spaces
AS, IN, NOT, NULL, IS, LIKE, BETWEEN, DISTINCT, ASC, DESCYesStays in place
CASE, WHEN, THEN, ELSE, ENDYesStays in place; a CASE expression remains on one line unless it contains AND, OR or a comma
COUNT, SUM, AVG, MIN, MAXYesStays in place
Every commaNot applicableLine break after it, next item indented two spaces
CREATE, ALTER, DROP, WITH, EXISTS, FULL, TOP, RETURNING, OVER, PARTITION BY, and every function other than the five aggregatesNoNot recognised; left as typed

Because BETWEEN x AND y contains AND, the upper bound moves to its own indented line.

Known limits to check before you rely on the output

  • Quoted strings are not protected. Keywords inside a string are recased and can be moved to a new line, and a comma inside a string gets a line break after it. This changes the stored or compared value.
  • Comments are not protected. All input is first joined into one line, so a line comment that starts with two dashes can absorb the code that followed it. select a, -- first then b from t on the next line comes back with b inside the comment.
  • Commas inside brackets break too. coalesce(nickname, 'n/a') and IN (1, 2, 3) are split across lines the same way a select list is.
  • Subqueries are not indented. An inner SELECT stays on the line of its opening bracket, and its FROM and WHERE start at the left margin like the outer ones, so nesting depth is not visible.
  • Compound joins split. LEFT JOIN becomes LEFT on one line and JOIN on the next. In LEFT OUTER JOIN or FULL OUTER JOIN, OUTER and JOIN each get a line, while the first word stays on the previous line and is not recased.
  • Identifiers that match a keyword are treated as keywords. Quote or rename columns called count, set, end, values, min or max, or fix them by hand afterwards.
  • There is one option only: keyword case. Indent width, comma position, line length and dialect cannot be set, and there is no minify mode.
  • It does not validate. Broken SQL is laid out without any warning.

SQL clause order: how it is written and when it runs

Putting one clause per line makes a query easier to reason about, because the database does not evaluate the clauses in the order they are written.

Written orderClauseLogical evaluation orderWhat it does
1SELECT5Chooses and computes the output columns
2FROM and JOIN ... ON1Builds the set of rows from the tables
3WHERE2Filters individual rows
4GROUP BY3Collapses rows into groups
5HAVING4Filters groups, so it can use aggregates
6ORDER BY6Sorts the result
7LIMIT and OFFSET7Keeps a slice of the sorted rows

This is why a column alias defined in SELECT cannot normally be used in WHERE, yet can be used in ORDER BY.

When a simple formatter is enough, and when it is not

A one-clause-per-line layout is all most people need to read a query quickly. Once each JOIN and its ON condition sit on their own lines, a missing join condition is obvious. Once the WHERE conditions are stacked, a filter on the wrong alias stands out, and so does an OR that needed brackets. In a pull request, a query laid out this way produces line-level diffs, so a reviewer sees which condition changed instead of one rewritten line.

This tool suits flat queries: a select list, a few joins, some conditions, a GROUP BY and an ORDER BY. It is a poor fit for stored procedures, CREATE TABLE scripts, common table expressions, window functions and anything with several levels of nested subqueries, because it has no notion of nesting and does not recognise those keywords. For that kind of SQL, use the formatter in your database client or editor, or a parser-based command-line formatter that you can also run in continuous integration.

Formatting is presentation only. It will not tell you that a query is slow or wrong. For that, run EXPLAIN in your database and read the plan.

How to use it

  1. 1

    Paste your query into the SQL query box. Existing line breaks and extra spaces are removed before formatting, so the input layout does not matter.

  2. 2

    Set Keyword case to UPPERCASE or lowercase.

  3. 3

    Read the result under Formatted SQL: one main clause per line, with conditions and list items indented two spaces.

  4. 4

    Compare any quoted text and comments against your original, then use copy or download to save the result as query.sql.

Frequently asked questions

Is my SQL sent to a server?
No. The formatting is a handful of text replacements that run in the page, so the query stays in your browser. That matters when a query contains internal table names or literal customer values.
Can it format several statements at once?
Yes, with a caveat. Each statement's clauses start new lines, so select 1; select 2; comes back as two lines. No blank line is added between statements, and any blank lines you had are removed.
Why is LEFT on a separate line from JOIN?
The tool breaks before LEFT JOIN as a unit and then again before the word JOIN. The result is LEFT alone on one line and JOIN starting the next. Databases ignore line breaks between the two words, so the query runs the same; rejoin them by hand if you prefer.
Does it indent subqueries or CTEs?
No. The FROM, WHERE and other clauses inside a subquery start at the left margin exactly like the outer query's clauses, and WITH is not a recognised keyword. Deeply nested SQL will be broken into lines but will not show its structure through indentation.
Can it minify SQL back to one line?
No. There is no compact mode. The only setting is Keyword case.
Will it uppercase function names?
Only the five aggregate names it knows: COUNT, SUM, AVG, MIN and MAX. Other functions such as coalesce, now, lower, cast or row_number are left in whatever case you typed.
What file does the download button save?
A plain text file named query.sql containing the formatted output exactly as shown, ready to commit next to a migration or attach to a ticket.
Why did a comma inside a function call start a new line?
Every comma is followed by a line break and a two-space indent, wherever it appears. The rule exists to put select-list items on separate lines, and it cannot tell those commas from the ones in function arguments, IN lists or VALUES lists.

Looking for something else? Browse all developer tools or see every tool.