Skip to the tool
DevToolBench

MySQL Formatter

Beautify MySQL, backticks and # comments included.

199 chars
# nightly upsert
INSERT INTO
  `daily_stats` (`day`, `views`)
SELECT
  date(created_at),
  COUNT(*)
FROM
  `page_views`
WHERE
  `path` <> "/health"
GROUP BY
  1
ON DUPLICATE KEY UPDATE
  `views` = VALUES(`views`);
Statements
1
Comments kept
1
Lines
14
Characters
213

MySQL syntax, before and after

  • Backticks quote reserved words used as names

    select `order`, `key` from `group` where `desc` = 1
    SELECT
      `order`,
      `key`
    FROM
      `group`
    WHERE
      `desc` = 1
  • LIMIT offset, count stays on one line

    select id from posts order by id limit 20, 10
    SELECT
      id
    FROM
      posts
    ORDER BY
      id
    LIMIT 20, 10
  • A # starts a comment that runs to the end of the line

    select id # primary key
    from users
    SELECT
      id # primary key
    FROM
      users
  • ON DUPLICATE KEY UPDATE, with VALUES() as a function

    insert into hits (k, n) values ('home', 1) on duplicate key update n = n + values(n)
    INSERT INTO
      hits (k, n)
    VALUES
      ('home', 1)
    ON DUPLICATE KEY UPDATE
      n = n + VALUES(n)
  • Without a space after it, -- is two minus signs

    select 5--1, 5 -- 1
    from dual
    SELECT
      5 - -1,
      5 -- 1
    FROM
      dual

Everything runs in your browser. Nothing you type is sent to a server.

Found a bug in this tool? Report it.

Share this tool

A MySQL formatter that reads MySQL

This MySQL formatter lays out a query with one clause per line and indented subqueries, but it reads the text by MySQL's rules rather than the SQL standard's. That difference is not cosmetic. A backtick, a # and a double quote each mean something in MySQL that they do not mean elsewhere, and a generic formatter that gets them wrong can split a string or swallow half a line into a comment.

The panel above opens with a MySQL upsert already loaded. Paste your own query over it; the dialect stays on MySQL, and you can still switch keyword case, indentation or minify the result. Nothing is sent anywhere — the formatting happens in your browser.

Backtick identifiers

MySQL quotes identifiers with backticks. They are how a table called order or a column called key can exist at all, since both are reserved words, and ORMs such as Laravel's query builder and many dump tools put backticks around every name out of caution. The formatter treats everything between two backticks as one token, including spaces and reserved words, and a doubled backtick inside is an escaped backtick rather than the end of the name.

Double quotes are the trap. Without the ANSI_QUOTES SQL mode, "text" in MySQL is a string, not a column. A query written for PostgreSQL that quotes column names with double quotes will run on MySQL and compare against literal strings instead, usually returning nothing and raising no error.

Comments: # and the space after --

MySQL accepts three comment styles. /* ... */ works as everywhere else, and # starts a comment that runs to the end of the line. The third is the one people trip on: -- only starts a comment when a space or a line break follows it. That rule exists so that 5--1 means five minus minus one. A formatter using standard rules would read it as 5 followed by a comment, and the output would drop part of your expression without saying so.

Strings follow MySQL too. A backslash escapes the next character, so 'it\'s' is one string, and that is also why a path like 'C:\new' holds a newline in MySQL.

LIMIT offset, count

LIMIT 20, 10 skips twenty rows and returns ten; the offset comes first. The formatter keeps both numbers on the LIMIT line, which is where you want them when checking pagination. When a query will outlive one database, LIMIT 10 OFFSET 20 says the same thing more plainly and also runs on PostgreSQL.

ON DUPLICATE KEY UPDATE

MySQL's upsert is an INSERT with an ON DUPLICATE KEY UPDATE clause, and the formatter gives that clause its own line with the assignments beneath it. Inside it, VALUES(col) is a function that refers to the value the insert tried to write, not a new VALUES list, so it stays glued to its parenthesis. On MySQL 8.0.20 and later, a row alias is the recommended replacement.

For queries that run on more than one database, the SQL formatter has the full list of layout rules, and the PostgreSQL formatter covers the other common dialect.

Frequently asked questions

Why does MySQL use backticks instead of double quotes?

Because by default MySQL treats double quotes as a second way to write a string. Backticks are its own identifier quote, and they are the only way to use a reserved word such as order or key as a column name. If the server runs with the ANSI_QUOTES SQL mode, double quotes become identifiers instead, which is why a query can behave differently on two servers with the same data.

Is LIMIT 20, 10 the same as LIMIT 10 OFFSET 20?

Yes. In the comma form the first number is the offset and the second is the row count, which is the reverse of what most people guess on first reading. MySQL accepts both spellings. The OFFSET form is also valid in PostgreSQL and SQLite, so it is the safer choice for a query that may move between databases.

Why did my -- comment not work?

MySQL only treats -- as a comment when it is followed by a space, a tab or a line break. Written as 5--1 it is five minus minus one, which is a deliberate choice so that arithmetic on negative numbers is not silently cut off. The formatter reads it the same way and shows it as 5 - -1, so the difference is visible.

What replaced VALUES() inside ON DUPLICATE KEY UPDATE?

From MySQL 8.0.20 the VALUES() function there is deprecated in favour of a row alias: INSERT ... VALUES (...) AS new ON DUPLICATE KEY UPDATE n = new.n. Both forms still run, and the formatter lays both out the same way. MariaDB has not deprecated VALUES() and does not support the alias.

Does this work for MariaDB?

Yes. MariaDB shares the MySQL tokeniser rules that matter for layout: backticks, # comments, backslash escapes in strings and the spacing rule for --. Pick the MySQL dialect for MariaDB queries.

Related tools

Updated