MySQL vs PostgreSQL: Key Syntax Differences
The MySQL vs PostgreSQL syntax differences that break migrations: auto-increment, quoting, string concat, upserts, and NULL functions — with side-by-side SQL.
Read postsqlfmt▍
Paste MySQL SQL to format it consistently and validate it against MySQL's actual grammar, including backtick-quoted identifiers and MySQL-only statements a generic formatter would misread.
select u.id, u.name, count(o.id) as order_count, sum(o.total) as lifetime_value from users u left join orders o on o.user_id = u.id where u.created_at >= '2026-01-01' and u.status in ('active', 'trial') group by u.id, u.name having count(o.id) > 0 order by lifetime_value desc limit 25;INSERT INTO
`orders` (`id`, `customer_id`, `total`)
VALUES
(1001, 42, 89.99)
ON DUPLICATE KEY UPDATE
total = values(`total`),
updated_at = now();Syntax looks valid — no misspelled keywords or anti-patterns found.
MySQL uses backticks, not double quotes, to quote identifiers that clash with reserved words or contain spaces. A formatter that only understands ANSI double-quoted identifiers will treat backtick-quoted names as a syntax error.
SELECT `order`, `group` FROM `user` WHERE `order`.status = 'active';MySQL's upsert syntax appends ON DUPLICATE KEY UPDATE to an INSERT, updating the row in place if it collides with a unique key instead of erroring. It has no equivalent clause in standard SQL, so generic validators often stumble on it.
INSERT INTO counters (id, hits) VALUES (1, 1) ON DUPLICATE KEY UPDATE hits = hits + Beyond standard SQL, sqlfmt's MySQL dictionary recognizes these as valid syntax:
The MySQL vs PostgreSQL syntax differences that break migrations: auto-increment, quoting, string concat, upserts, and NULL functions — with side-by-side SQL.
Read postSingle quotes are for string values, double quotes are for identifiers — but MySQL, SQL Server, and BigQuery bend the rule. The full guide, with examples.
Read postReserved words like ORDER, GROUP, and USER silently break SQL queries used as column names. See which words are reserved per dialect and how to quote them.
Read postYes. Backticks are parsed as MySQL identifier quoting, not as a syntax error, and preserved exactly as written in the formatted output.
Yes — sqlfmt's MySQL dictionary includes REPLACE, LOAD, LOCK/UNLOCK TABLES, ANALYZE, and OPTIMIZE as valid statement starters, so they're recognized rather than flagged.
Yes — all five dialects, including MySQL, are free with no account required. Pro adds unlimited daily analyses, live formatting as you type, saved snippets, and REST API access.
No. Formatting and validation run entirely in your browser; your SQL is only sent anywhere if you choose to save a snippet or create a share link while signed in.
GROUP_CONCAT rolls the values from a grouped column into one delimited string per group — MySQL's version of an aggregate string join that other dialects spell differently or lack entirely.
SELECT customer_id, GROUP_CONCAT(product_name SEPARATOR ', ') FROM orders GROUP BY customer_id;MySQL adds whole statement types standard SQL doesn't have — REPLACE (insert-or-overwrite), LOAD DATA, LOCK/UNLOCK TABLES, and OPTIMIZE TABLE among them. sqlfmt's MySQL dictionary recognizes each as a valid way to start a statement, rather than flagging the first word as unexpected.
LOAD DATA INFILE '/tmp/users.csv' INTO TABLE users FIELDS TERMINATED BY ',';