Skip to content

Runs entirely in your browser. Nothing you paste leaves this page.

Free / No sign-up

SQL formatter and beautifier.

Format or minify SQL for PostgreSQL, MySQL, SQL Server, SQLite, BigQuery and Snowflake. Pick keyword case and indentation, and see unclosed quotes and brackets by line and column.

Mode
Keyword case
Indentation

Formatted

WITH
  recent AS (
    SELECT
      user_id,
      COUNT(*) AS orders,
      SUM(total) AS spend
    FROM
      orders
    WHERE
      created_at >= NOW() - INTERVAL '30 days'
      AND status IN ('paid', 'shipped')
    GROUP BY
      user_id
  )
SELECT
  u.id,
  u.email,
  COALESCE(r.orders, 0) AS orders,
  CASE
    WHEN r.spend > 1000 THEN 'vip'
    WHEN r.spend > 0 THEN 'active'
    ELSE 'idle'
  END AS tier
FROM
  users u
  LEFT JOIN recent r ON r.user_id = u.id
WHERE
  u.deleted_at IS NULL
  AND u.created_at BETWEEN '2026-01-01' AND '2026-09-30'
ORDER BY
  r.spend DESC NULLS LAST
LIMIT 50;

1 statement formatted for PostgreSQL. Only whitespace and keyword case change; identifiers, strings and comments stay as written.

How to use it.

  1. 01

    Paste a query or load the sample, then pick your database dialect.

  2. 02

    Choose Format or Minify, keyword case (UPPER, lower or keep) and the indent width.

  3. 03

    Copy the result. If a quote or bracket is never closed, press Show me to jump to it.

What it does.

Everything this tool handles, all of it inside your browser tab.

  • Formats or minifies as you type
  • Seven dialects: PostgreSQL, MySQL/MariaDB, SQL Server, SQLite, BigQuery, Snowflake and standard SQL
  • Keyword case: UPPER, lower or keep as written
  • Indent with 2 spaces, 4 spaces or tabs
  • Subqueries, CTEs, CASE blocks and CREATE TABLE columns laid out as indented blocks
  • Unclosed strings, comments, quoted identifiers and brackets located by line and column
  • Syntax-coloured output with one-click copy
  • Never changes names, strings, comments or dollar-quoted bodies
  • Runs entirely in your browser: no upload, no sign-up

Worked examples.

  • Format a JOIN query

    select o.id, c.name, o.total from orders o inner join customers c on c.id = o.customer_id where o.status = 'paid' and o.total > 100 order by o.total desc limit 20
    
    > SELECT
      o.id,
      c.name,
      o.total
    FROM
      orders o
      INNER JOIN customers c ON c.id = o.customer_id
    WHERE
      o.status = 'paid'
      AND o.total > 100
    ORDER BY
      o.total DESC
    LIMIT 20

    PostgreSQL dialect, UPPER keywords, 2-space indent. Names and string values are untouched.

  • CASE expressions on separate lines

    select id, case when score >= 90 then 'A' when score >= 75 then 'B' else 'C' end as grade from results
    
    > SELECT
      id,
      CASE
        WHEN score >= 90 THEN 'A'
        WHEN score >= 75 THEN 'B'
        ELSE 'C'
      END AS grade
    FROM
      results

    Each branch gets its own line and END lines up with CASE, so adding a grade is a one-line change.

  • Find an unclosed quote

    select * from users where name = 'O''Brien and id = 4
    
    > Unterminated string: the ' opened here is never closed at line 1, column 34.

    The doubled quote in O''Brien is a correct escape, but the closing quote after Brien is missing, so the string runs to the end of the query.

  • SQL Server brackets and TOP

    select top 5 [Order ID], CustomerName from dbo.Orders with (nolock) where OrderDate >= dateadd(day, -7, getdate())
    
    > SELECT
      TOP 5 [Order ID],
      CustomerName
    FROM
      dbo.Orders WITH (nolock)
    WHERE
      OrderDate >= DATEADD(day, -7, GETDATE())

    With the SQL Server dialect, [Order ID] is one quoted identifier. Under PostgreSQL the brackets would be read as array syntax instead.

  • Minify for a log line or config

    SELECT
      id,
      email -- primary contact
    FROM
      users
    WHERE
      active = TRUE;
    
    > SELECT id, email FROM users WHERE active = TRUE;

    Line comments are dropped when minifying, because anything after -- would otherwise swallow the rest of the line.

What this SQL formatter does

It re-flows SQL into a consistent, reviewable layout, or squeezes it onto one line per statement. A tokenizer written for this page reads your query the way the chosen database would: which characters quote identifiers, which start comments, how strings escape quotes and what counts as a parameter. The formatter then rebuilds the whitespace around those tokens.

Only two things ever change: whitespace and the case of SQL keywords. Table and column names, string literals, quoted identifiers, comments and PostgreSQL dollar-quoted function bodies are written back exactly as you typed them. That makes the output safe to paste straight back into a migration, a dbt model or a stored procedure.

It is a layout tool, not a full SQL parser, so it does not rewrite queries or check that a column exists. Your database is still the final judge of correctness, as described in our PostgreSQL indexing guide when you move on to EXPLAIN.

The layout it uses, and why

Each clause (SELECT, FROM, WHERE, GROUP BY, ORDER BY, HAVING and so on) starts a line, with its contents indented beneath it. Select lists put one column per line. Conditions start with AND or OR. JOINs sit under FROM with their ON condition on the same line. CASE expressions put each WHEN on its own line, subqueries and CTE bodies become indented blocks, and CREATE TABLE lists one column per line. Short clauses such as LIMIT 50 stay on one line.

The reason is code review. With one column or condition per line, adding a filter changes one line in the diff instead of rewriting a long one, and a leading AND lets you comment a condition out without touching its neighbours. Window clauses such as OVER (PARTITION BY team ORDER BY score) and IN lists stay inline because breaking them up hurts readability.

Other conventions exist, such as comma-first lists or right-aligned river style. Pick one for the team and enforce it in CI with a linter such as SQLFluff, so formatting never comes up in review again.

Dialect differences that matter

Identifiers: standard SQL, PostgreSQL, SQLite and Snowflake quote them with double quotes. MySQL and BigQuery use backticks. SQL Server uses [square brackets] (SQLite accepts them too). Pick the wrong dialect and a backtick in PostgreSQL is reported as an error, which is exactly what the database would do.

Strings: MySQL and BigQuery also accept double-quoted strings and backslash escapes. PostgreSQL has E'...' escape strings and $tag$ dollar quoting for function bodies; BigQuery has raw strings r'...' and triple-quoted strings. Comments: -- and /* */ everywhere, plus # in MySQL and BigQuery.

Parameters differ by driver: $1 in PostgreSQL, @name in SQL Server and BigQuery, ? in MySQL and SQLite drivers, :name in many ORMs. PostgreSQL operators such as ::, ->> and @> are kept intact. For a wider comparison of the two most common open-source databases, see PostgreSQL vs MySQL.

Uppercase or lowercase SQL keywords?

SQL keywords are case-insensitive, so SELECT and select run identically and there is no performance difference. Uppercase keywords are the tradition in documentation and help keywords stand out from names in plain-text editors. Lowercase is common in analytics code, and dbt's published style guide recommends it. Keep is there when you only want the layout.

Identifiers are another matter, which is why the formatter never touches them. PostgreSQL folds unquoted names to lowercase, Snowflake folds them to uppercase, and whether MySQL table names are case-sensitive depends on the operating system and the lower_case_table_names setting. Changing the case of a name could point a query at a different object.

What the error messages mean

An unterminated string is reported at the quote that opens it, which is usually where the real mistake is: an apostrophe in a name such as O'Brien must be doubled as O''Brien. An unclosed bracket is reported at the earliest ( that never closes, and a stray ) at the bracket itself. Unclosed block comments, quoted identifiers and dollar-quoted strings are caught the same way.

Show me selects the exact character in the input so you can fix it in place. Mistakes that are valid at the token level, such as a missing comma or a misspelt keyword, are not detected here; your database's parser reports those with its own line number.

Formatting SQL in a team workflow

A formatter in the browser is handy for one-off queries: a slow query from a log, a statement copied out of an ORM's debug output, or a view definition pulled from the information schema. Format it and the structure is obvious at a glance: which tables are joined, which filters apply and where each subquery starts.

For SQL that lives in a repository, automate it. Most teams format in the editor and check again in CI, so every migration and analytics model arrives in review already formatted. SQLFluff covers many dialects and integrates with dbt; database IDEs and the popular editor SQL extensions have formatters of their own. Configure one, commit the configuration and reformat the whole codebase in a single commit, so later diffs only show real changes.

Formatted SQL also makes performance work easier. With each join and filter on its own line, it is simple to line the query up against its EXPLAIN plan and spot a missing index or a filter that cannot use one. When schema changes are involved, plan them as zero-downtime migrations.

Is it safe to paste production SQL here?

Yes. Tokenizing and formatting run in JavaScript inside this tab, with no upload and no logging, so table names, customer values in WHERE clauses and internal schemas never leave your machine.

Minify drops ordinary comments but keeps optimizer hints written as /*+ ... */ and MySQL versioned comments /*! ... */, because those change how the query runs. And remember that formatting is not sanitising: building SQL by joining strings is how SQL injection happens, so always send user input as bound parameters.

Questions, answered

Something else on your mind? Ask a consultant and get a reply within one business day.

Is my SQL sent to a server?

No. The tokenizer and formatter run in JavaScript in this tab. Nothing is uploaded or logged, so it is safe for production queries and internal schemas.

Does formatting change what my query does?

No. Only whitespace and the case of SQL keywords change. Identifiers, string values, comments and dollar-quoted function bodies are kept exactly as written.

Which SQL dialects are supported?

PostgreSQL, MySQL and MariaDB, SQL Server (T-SQL), SQLite, BigQuery, Snowflake and standard SQL. The dialect decides how quotes, comments, escapes and parameters are read.

Should SQL keywords be uppercase?

It is a style choice; databases treat keywords case-insensitively and there is no speed difference. Uppercase is traditional, lowercase is popular in analytics code. Pick one per project and stay consistent.

Why does a backtick show an error in PostgreSQL?

PostgreSQL quotes identifiers with double quotes, not backticks, and rejects them. Switch the dialect to MySQL, BigQuery or SQLite if that is where the query runs.

Can it validate my SQL?

Partly. It catches unclosed strings, comments, quoted identifiers and brackets. It is not a full parser, so a missing comma or a misspelt keyword is left for your database to report.

Does it handle stored procedures and functions?

It formats the surrounding statement and leaves function bodies in dollar quotes or strings untouched. Procedural blocks (PL/pgSQL, T-SQL BEGIN...END) are formatted as plain statements, so review long procedures by eye.

What does Minify do with comments?

It removes -- and ordinary /* */ comments, but keeps optimizer hints such as /*+ INDEX(...) */ and MySQL versioned comments /*! ... */, which affect how the query runs.

Can I format several statements at once?

Yes. Statements separated by semicolons are formatted one after another with a blank line between them, and the status line shows how many it found.

More free tools.

All tools

Need tooling like this inside your product?

We build internal tools, developer platforms and APIs. Tell us what your team keeps doing by hand.