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 PostgreSQL SQL to format it consistently and validate it against Postgres's actual grammar — including dialect-specific syntax generic formatters often flag as invalid.
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;SELECT
id,
data ->> 'email' AS email
FROM
events
WHERE
data @> '{"type": "signup"}'
AND data ->> 'email' ILIKE '%@example.com'
ORDER BY
id DESC
LIMIT
10;Syntax looks valid — no misspelled keywords or anti-patterns found.
Postgres allows $$...$$ (or a tagged $tag$...$tag$) as an alternative to single-quoting a string, so you can write a function body or a string containing apostrophes without escaping every quote. A formatter that only knows standard SQL string literals will misparse or mangle these.
CREATE FUNCTION greet() RETURNS text AS $$
SELECT 'hello, ' || 'world';
$$ LANGUAGE sql;ILIKE is Postgres's case-insensitive counterpart to LIKE. It isn't standard SQL, so a formatter built only against the ANSI grammar treats it as an unknown token; sqlfmt's PostgreSQL dictionary recognizes it as a keyword.
SELECT * FROM users WHERE email ILIKE '%@example.com';INSERT, UPDATE, and DELETE can all end with a RETURNING clause, handing back the affected rows without a second round-trip query. It's a Postgres-only extension that a generic parser can misread as the start of a new statement.
Beyond standard SQL, sqlfmt's PostgreSQL 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 postSQL Server vs PostgreSQL syntax differences: TOP vs LIMIT, IDENTITY vs SERIAL, + vs || concatenation, GETDATE() vs NOW(), and more, with side-by-side SQL.
Read postSQLite vs PostgreSQL syntax differences that break migrations: dynamic typing, AUTOINCREMENT vs SERIAL/IDENTITY, JOIN support, dates, and ALTER TABLE.
Read postYes — sqlfmt parses SQL against Postgres's real grammar, so ILIKE, RETURNING, dollar-quoted strings, and JSONB operators are recognized as valid syntax instead of being flagged as errors.
Yes. Operators like ->, ->>, and @> for querying JSONB columns are parsed correctly and left untouched by the formatter.
Yes — all five dialects, including PostgreSQL, 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.
DELETE FROM sessions WHERE expires_at < now() RETURNING id;Postgres's JSONB type comes with its own operators — ->, ->>, and @> among them — for reaching into JSON documents directly in SQL. These aren't standard operators, so validators without dialect awareness often report them as syntax errors.
SELECT data->>'email' AS email FROM events WHERE data @> '{"type": "signup"}';