This is a searchable SQL syntax cheatsheet covering the keywords, clauses and functions you use every day. Each entry gives the syntax pattern, a one-line description, and — where the dialects diverge — notes for MySQL, PostgreSQL, SQLite and SQL Server, so you can write portable queries or adapt one to a specific engine.
How it works
SQL is largely standardised by ANSI, but every database adds its own spellings for common tasks. The reference is grouped so you can browse by area: Query (SELECT, DISTINCT, CTEs), Clause (WHERE, GROUP BY, HAVING, ORDER BY, LIMIT), Join types, DML (INSERT, UPDATE, DELETE, upsert), DDL (CREATE, ALTER, DROP, indexes), aggregate and scalar functions, window functions and transactions. Search matches the keyword, the syntax and the dialect notes, so a query for “pagination” or “auto increment” surfaces the right entries even if you do not remember the exact keyword.
Logical execution order — the most useful thing in SQL
The single most useful thing to internalise is the order in which SQL logically executes a SELECT:
FROM → WHERE → GROUP BY → HAVING → SELECT → DISTINCT → ORDER BY → LIMIT
This order explains several common confusions:
- A column alias defined in
SELECTcannot be used inWHERE(SELECT hasn’t run yet), but can be used inORDER BY(which runs after). WHEREfilters individual rows before grouping;HAVINGfilters groups after aggregation. You cannot put an aggregate likeCOUNT(*)inside aWHEREclause.DISTINCTruns afterSELECTbuilds the output column list but beforeORDER BY.
Key dialect differences at a glance
| Feature | MySQL | PostgreSQL | SQLite | SQL Server |
|---|---|---|---|---|
| Auto-increment | AUTO_INCREMENT | SERIAL / GENERATED | AUTOINCREMENT | IDENTITY |
| Upsert | INSERT ... ON DUPLICATE KEY UPDATE | INSERT ... ON CONFLICT DO UPDATE | INSERT OR REPLACE | MERGE |
| Pagination | LIMIT n OFFSET m | LIMIT n OFFSET m | LIMIT n OFFSET m | OFFSET n ROWS FETCH NEXT m ROWS ONLY |
| Full outer join | Not supported | Supported | Not supported | Supported |
| String concat | CONCAT(a, b) | a || b | a || b | a + b |
| Current timestamp | NOW() | NOW() | datetime('now') | GETDATE() |
Tips and gotchas
Watch the dialect notes for the big traps: FULL OUTER JOIN is missing in MySQL and SQLite, auto-increment is spelled four different ways, and upsert syntax differs by engine.
Common mistakes:
- Using a
SELECTalias inWHEREinstead ofHAVINGor a subquery. - Forgetting that
NULL != NULL— useIS NULLandIS NOT NULL, not= NULL. LIKEwith a leading wildcard (LIKE '%term') cannot use an index and causes a full scan.- Mixing implicit and explicit joins in the same query — always use explicit
JOIN ... ON.
Everything runs in your browser; this tool never connects to a database or uploads your input.