SQL doesn't have an equivalent of Prettier or gofmt that the whole ecosystem has converged on — every team, and often every developer on the same team, writes it slightly differently. That's not necessarily a problem, but inconsistent SQL is genuinely harder to review and debug than inconsistent application code, because a misread JOIN condition or a missed WHERE clause can silently return wrong data instead of throwing an error.
Keyword Casing: Pick One and Enforce It
The classic convention is uppercase for SQL keywords, lowercase for identifiers:
SELECT customer_id, order_date, total_amount
FROM orders
WHERE status = 'completed'
AND order_date >= '2026-01-01'
ORDER BY order_date DESC;
This isn't required by any SQL standard — it's purely a readability convention, but it's a genuinely useful one: uppercase keywords visually separate "SQL grammar" from "your data," making it faster to scan a query for its structure before reading the specifics. All-lowercase SQL is increasingly common too, especially among teams that write a lot of it in ORMs or generated code, and there's nothing wrong with picking that instead — the only real mistake is mixing the two within the same codebase.
Indentation for Joins
The most readable convention for multi-join queries aligns each JOIN at the same indentation as FROM, with the ON condition indented one level further:
SELECT o.order_id, c.name, p.title
FROM orders o
JOIN customers c
ON o.customer_id = c.id
JOIN order_items oi
ON oi.order_id = o.order_id
JOIN products p
ON oi.product_id = p.id
WHERE o.status = 'completed';
Always alias tables when joining more than one, and keep the alias short but meaningful (o for orders, c for customers) rather than single arbitrary letters that require the reader to scroll back up to decode. When a query has four or more joins, resist the urge to write it as one unbroken block — the visual repetition of JOIN ... ON ... on its own lines is doing real work to help the next reader trace the relationships.
WHERE Clauses With Multiple Conditions
Put each condition on its own line with the boolean operator leading, not trailing:
-- Easier to scan and modify
WHERE status = 'completed'
AND total_amount > 100
AND region IN ('US', 'CA', 'UK')
-- Harder to scan, easy to miss a condition when skimming
WHERE status = 'completed' AND total_amount > 100 AND region IN ('US', 'CA', 'UK')
Leading operators make it trivial to comment out a single condition during debugging without breaking the query's syntax — a small thing, but one of those habits that pays for itself constantly.
Where Dialects Actually Diverge
Formatting conventions are mostly universal, but a few real syntax differences matter enough to call out:
Quoting identifiers. MySQL uses backticks for identifiers that need escaping (reserved words, names with spaces); Postgres and standard SQL use double quotes; SQL Server (T-SQL) uses square brackets.
-- MySQL
SELECT `order`, `date` FROM `orders`;
-- Postgres / ANSI SQL
SELECT "order", "date" FROM "orders";
-- SQL Server
SELECT [order], [date] FROM [orders];
LIMIT vs TOP vs FETCH. MySQL and Postgres use LIMIT n; SQL Server traditionally uses SELECT TOP n; the ANSI-standard form (FETCH FIRST n ROWS ONLY) works in Postgres and modern SQL Server but not MySQL. If you're writing SQL that needs to run against more than one engine, this is the single most common thing that breaks.
String concatenation. Postgres and Oracle use ||; MySQL uses the CONCAT() function (|| in MySQL means logical OR by default); SQL Server uses +. There's no portable syntax here — you either write per-dialect SQL or push concatenation into the application layer.
A Practical Habit: Format Before You Commit
Inconsistently formatted SQL in a migration file or a saved query is one of those things that seems harmless until someone else has to modify it under time pressure and misreads a condition because of poor indentation. For one-off formatting — pasting in a messy query from a colleague, a generated migration, or something copied out of a BI tool — our SQL Formatter reformats it with consistent keyword casing and indentation across MySQL, PostgreSQL, SQLite, and T-SQL dialects, entirely in your browser.
Summary
- Pick one keyword-casing convention (upper or lower) and apply it consistently — mixing both is the actual readability problem, not the choice itself.
- Align joins under
FROM, indentONconditions one level deeper, and alias every joined table. - Lead
WHEREconditions with the boolean operator so individual conditions are easy to comment out while debugging. - Watch for real dialect differences — identifier quoting,
LIMIT/TOP/FETCH, and string concatenation — these aren't style choices, they're syntax that won't run on the wrong engine.