DEV Community

Snappy Tools
Snappy Tools

Posted on

SQL Formatting: Why It Matters More Than You Think (and How to Do It Right)

Nobody disputes that code should be readable. But somehow, SQL gets a pass — compressed into a single line, aliases that are single letters, subqueries nested four levels deep. Here's why that's a mistake and what good SQL formatting actually looks like.

Why SQL Formatting Gets Ignored

A few reasons SQL readability gets neglected:

  1. It "works" either way. The database doesn't care about whitespace.
  2. ORMs hide the SQL. Developers who write Hibernate or SQLAlchemy rarely see raw SQL.
  3. No enforced style guide. Python has PEP 8; SQL has no universally adopted equivalent.
  4. Copy-paste culture. SQL often comes from Stack Overflow or query builders, pre-minified.

The cost shows up in code review ("wait, what does this actually do?"), debugging ("where does this subquery start?"), and onboarding ("who wrote this and can I call them?").

The Core Rules

Keywords in uppercase (or consistently lower)

Pick one and stick to it. Most style guides prefer uppercase keywords because it creates visual hierarchy:

-- Good
SELECT id, name, email
FROM users
WHERE created_at > '2026-01-01'
  AND is_active = true
ORDER BY name ASC;

-- Acceptable (consistent lowercase)
select id, name, email
from users
where created_at > '2026-01-01'
  and is_active = true
order by name asc;
Enter fullscreen mode Exit fullscreen mode

One clause per line

Each major clause (SELECT, FROM, WHERE, JOIN, GROUP BY, ORDER BY) starts on its own line. Conditions within a clause are indented:

SELECT
    u.id,
    u.name,
    COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o
    ON o.user_id = u.id
WHERE u.is_active = true
    AND u.created_at > '2026-01-01'
GROUP BY u.id, u.name
HAVING COUNT(o.id) > 0
ORDER BY order_count DESC
LIMIT 100;
Enter fullscreen mode Exit fullscreen mode

Alias everything, but name it well

Single-letter aliases (u, o) are fine in short queries. In long queries, use descriptive aliases:

-- Short: fine
SELECT u.id FROM users u JOIN orders o ON o.user_id = u.id;

-- Long: be descriptive
SELECT 
    active_users.id,
    recent_orders.total
FROM users AS active_users
JOIN orders AS recent_orders
    ON recent_orders.user_id = active_users.id;
Enter fullscreen mode Exit fullscreen mode

Subqueries: always indent

SELECT *
FROM (
    SELECT 
        user_id,
        SUM(amount) AS total_spent
    FROM orders
    WHERE status = 'completed'
    GROUP BY user_id
) AS spending
WHERE spending.total_spent > 1000;
Enter fullscreen mode Exit fullscreen mode

CTEs over nested subqueries

Common Table Expressions make complex logic readable:

WITH active_users AS (
    SELECT id, name
    FROM users
    WHERE is_active = true
),
high_spenders AS (
    SELECT user_id, SUM(amount) AS total
    FROM orders
    GROUP BY user_id
    HAVING SUM(amount) > 1000
)
SELECT 
    au.name,
    hs.total
FROM active_users au
JOIN high_spenders hs
    ON hs.user_id = au.id
ORDER BY hs.total DESC;
Enter fullscreen mode Exit fullscreen mode

Formatting Reference

Element Convention
Keywords UPPERCASE
Table/column names lowercase_snake_case
Aliases AS keyword (explicit)
Commas End of line (trailing) or start of line (leading) — pick one
Indentation 4 spaces (not tabs)
Line length Max 100 chars
Semicolons Always close statements

Tools That Help

Running raw SQL through a formatter before committing it takes about 5 seconds and saves everyone who reads it later 5 minutes.

SnappyTools SQL Formatter & Beautifier formats any SQL query in the browser — supports indentation, keyword casing, and basic dialect-aware formatting. Paste in the ugly version, copy out the clean version.

No account, no upload, runs locally in your browser.


Do you have a team SQL style guide? Or does every developer format differently?

Top comments (0)