SQL Formatting Best Practices
Well-formatted SQL is the difference between a query you can debug in 30 seconds and one that takes 30 minutes. When a query fails at 2 AM, formatting is not cosmetic — it is operational. Yet SQL formatting is inconsistent across teams, with debates about uppercase keywords, indent depth, and comma placement that never resolve.
This guide establishes practical formatting rules with reasoning, so you can pick a style, enforce it, and move on.
Why Format SQL?
Unformatted SQL is common in production:
SELECT u.id, u.name, u.email, o.total, o.created_at FROM users u JOIN orders o ON u.id = o.user_id WHERE o.status = 'completed' AND o.total > 100 ORDER BY o.created_at DESC LIMIT 20;
The same query, formatted:
SELECT
u.id,
u.name,
u.email,
o.total,
o.created_at
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.status = 'completed'
AND o.total > 100
ORDER BY o.created_at DESC
LIMIT 20;
Formatted SQL makes it obvious:
- Which columns are selected
- Which tables are joined and how
- What filters are applied
- How results are ordered
Rule 1: One Clause Per Line
Each major clause (SELECT, FROM, WHERE, JOIN, ORDER BY, GROUP BY, HAVING, LIMIT) starts on its own line:
SELECT count(*) AS total
FROM orders
WHERE created_at >= '2024-01-01'
AND status = 'completed'
GROUP BY customer_id
HAVING count(*) > 5
ORDER BY total DESC
LIMIT 10;
Rule 2: Indent Continuation Lines
Columns in SELECT, conditions in WHERE, and join conditions continue with consistent indentation (2 or 4 spaces):
SELECT
u.name,
u.email,
count(o.id) AS order_count,
sum(o.total) AS lifetime_value
FROM users u
Rule 3: Uppercase Keywords
SQL keywords in UPPERCASE distinguish them from identifiers:
SELECT name FROM users WHERE id = 42 ORDER BY created_at DESC;
Not everyone agrees on this — lowercase keywords are more readable to some developers, and syntax highlighting makes case irrelevant in most editors. Pick one style for your team and enforce it.
Rule 4: One Column Per Line in SELECT
For more than 2-3 columns, put each on its own line:
SELECT
u.id,
u.name,
u.email,
u.created_at,
count(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.name, u.email, u.created_at;
Rule 5: Align JOINs
Each JOIN gets its own line with the ON condition:
FROM orders o
JOIN users u ON u.id = o.user_id
JOIN products p ON p.id = o.product_id
LEFT JOIN reviews r ON r.order_id = o.id
AND r.deleted_at IS NULL;
Multi-condition joins indent the additional conditions.
Rule 6: Format CTEs Clearly
Common Table Expressions (CTEs) are the modern way to structure complex queries. Format each CTE as a named block:
WITH monthly_revenue AS (
SELECT
date_trunc('month', created_at) AS month,
sum(total) AS revenue
FROM orders
WHERE status = 'completed'
GROUP BY 1
),
growth AS (
SELECT
month,
revenue,
lag(revenue) OVER (ORDER BY month) AS prev_revenue,
round(
(revenue - lag(revenue) OVER (ORDER BY month))
/ lag(revenue) OVER (ORDER BY month) * 100,
1
) AS growth_pct
FROM monthly_revenue
)
SELECT *
FROM growth
WHERE growth_pct IS NOT NULL
ORDER BY month;
Rule 7: Subqueries Get Full Formatting
Inline subqueries are formatted with the same rules, indented one level:
SELECT *
FROM users
WHERE id IN (
SELECT user_id
FROM orders
WHERE total > 1000
AND created_at >= '2024-01-01'
);
Comma Placement: Leading vs Trailing
Trailing commas (more common):
SELECT
name,
email,
created_at
Leading commas (easier to comment out lines):
SELECT
name
, email
, created_at
Both are valid. Pick one for your team. Most formatters default to trailing commas.
Dialect Differences
Different databases have different keywords, functions, and syntax:
| Feature | PostgreSQL | MySQL | SQL Server | SQLite |
|---|---|---|---|---|
| String concat | || | CONCAT() | + | || |
| Auto increment | SERIAL / GENERATED | AUTO_INCREMENT | IDENTITY | AUTOINCREMENT |
| Limit | LIMIT n | LIMIT n | TOP n | LIMIT n |
| Boolean | TRUE/FALSE | 1/0 | 1/0 | 1/0 |
A good formatter supports multiple dialects and adjusts keyword recognition accordingly.
Enforcing Consistency
- Use an automated formatter — manual formatting drifts. Run a formatter in CI or as a pre-commit hook.
- Document your style — one page in your wiki: indent size, keyword case, comma placement, CTE style.
- Format on save — editor plugins that format SQL on save eliminate style debates in code review.
Format Your SQL
StackCache SQL Formatter formats SQL for 13 dialects including PostgreSQL, MySQL, SQLite, SQL Server, Oracle, BigQuery, and Snowflake. Paste your query, choose your dialect, and get consistently formatted output — all locally in your browser.
Try it yourself
Open the tool mentioned in this guide — it runs locally in your browser, no account needed.
Open tool