You've seen it. SQL that looks like this:
SELECT u.id,u.name,u.email,o.total,o.created_at FROM users u INNER JOIN orders o ON u.id=o.user_id WHERE u.active=1 AND o.total>100 ORDER BY o.created_at DESC LIMIT 50
It works. It runs. Nobody can read it.
This is one of the most common problems in codebases that have been around longer than six months. SQL gets written fast, pasted from Stack Overflow, or auto-generated — and nobody ever cleans it up. Until something breaks and you have to debug it at 11pm.
Why SQL Formatting Matters More Than You Think
Readability is correctness. When SQL is unformatted, you miss bugs that would be obvious in clean code. A missing JOIN condition, a wrong column alias, a filter applied to the wrong table — these hide in the noise.
Code reviews become useless. Reviewing a 200-character single-line query is nearly impossible. Reviewers nod and move on. Formatted SQL is reviewable SQL.
Debugging is 10× faster. When a query produces wrong results, the first thing you do is read it. If you can't read it, you can't debug it.
Future you will thank you. You'll come back to this query in six months. You won't remember what it does. Formatted code has a much better chance of surviving contact with a tired developer.
The SQL Formatting Conventions That Actually Matter
There's no single SQL standard for formatting, but there are conventions that most experienced engineers agree on:
1. Uppercase keywords
-- Bad
select id, name from users where active = 1
-- Good
SELECT id, name FROM users WHERE active = 1
Uppercase keywords make the structure of a query visually scannable. Your eye immediately jumps to SELECT, FROM, WHERE and understands the structure before reading the details.
2. One clause per line
-- Bad
SELECT id, name FROM users WHERE active = 1 AND created_at > '2024-01-01' ORDER BY name
-- Good
SELECT
id,
name
FROM users
WHERE active = 1
AND created_at > '2024-01-01'
ORDER BY name
This is the single highest-impact change. Each clause gets its own line. You can comment out a WHERE condition without restructuring the whole query.
3. Indent column lists
When you have more than 2 or 3 columns in a SELECT, list them vertically with consistent indentation:
SELECT
u.id,
u.name,
u.email,
o.total,
o.status
FROM users u
JOIN orders o ON u.id = o.user_id
4. Align JOIN conditions
-- Harder to scan
JOIN orders o ON u.id=o.user_id
LEFT JOIN products p ON o.product_id=p.id
-- Easier to scan
JOIN orders o ON u.id = o.user_id
LEFT JOIN products p ON o.product_id = p.id
5. Use table aliases consistently
Short, meaningful aliases make complex queries readable. u for users, o for orders, p for products. Don't use single letters for tables with non-obvious names.
Dialect Differences That Trip People Up
SQL has a standard (SQL-92, SQL:2003, SQL:2016...) but every database implements a slightly different dialect. Some formatting differences matter for correctness, not just style:
String quoting:
- PostgreSQL and SQLite: single quotes for strings
'value', double quotes for identifiers"column_name" - MySQL: both
'value'and"value"work for strings; backticks for identifiers`column_name` - SQL Server (T-SQL): single quotes for strings, square brackets for identifiers
[column_name]
Date functions:
- PostgreSQL:
NOW()orCURRENT_TIMESTAMP - MySQL:
NOW()orSYSDATE() - SQL Server:
GETDATE()orSYSDATETIME() - SQLite:
datetime('now')
Limiting results:
- PostgreSQL, MySQL, SQLite:
LIMIT 10 - SQL Server:
TOP 10(in the SELECT) - Oracle:
ROWNUM <= 10(in WHERE) orFETCH FIRST 10 ROWS ONLY
When formatting SQL, always know which dialect you're targeting. A formatter that understands dialect differences will handle keyword casing and function names correctly for your database.
Common SQL Formatting Anti-Patterns
*SELECT **: Not a formatting issue, but often appears in messy SQL. If you're formatting for readability, replace SELECT * with explicit column names.
Implicit joins: Old-style comma joins in FROM are harder to read and reason about:
-- Old style (avoid)
SELECT * FROM users, orders WHERE users.id = orders.user_id
-- Modern style
SELECT * FROM users JOIN orders ON users.id = orders.user_id
No aliasing on subqueries: Give every subquery a name:
-- Hard to read
SELECT * FROM (SELECT id, COUNT(*) FROM orders GROUP BY id)
-- Better
SELECT * FROM (SELECT id, COUNT(*) AS order_count FROM orders GROUP BY id) AS order_summary
Magic numbers in WHERE: WHERE status = 2 — what's 2? Use constants or comments.
Automating SQL Formatting
For production codebases, consider adding SQL formatting to your workflow:
-
sqlfluff— Python-based SQL linter and formatter with dialect support -
pgFormatter— PostgreSQL-focused formatter -
Prettier with
prettier-plugin-sql— formats SQL inside JavaScript/TypeScript projects - IDE plugins: VS Code SQL Formatter, DataGrip (JetBrains) has it built in
For quick one-off formatting when you're debugging or writing a query, a browser-based tool is faster than setting up a local tool. SnappyTools SQL Formatter handles 19 SQL dialects including PostgreSQL, MySQL, SQL Server, SQLite, BigQuery, and Snowflake — paste, format, copy. No signup.
The 30-Second Workflow
When you inherit messy SQL (it will happen), here's the fastest path to readable:
- Paste into a formatter
- Set dialect to match your database
- Set indent to 2 spaces (4 can feel overwhelming for complex queries)
- Format
- Read the output carefully — formatting often reveals bugs
- Copy and replace the original
That last step is important. If you can't understand the formatted version, you probably have a logic bug hiding in the noise.
Clean SQL is not a vanity preference. It's maintainable code. The five minutes you spend formatting a query now will save you an hour of debugging confusion later.
Need to format SQL fast? SnappyTools SQL Formatter supports 19 dialects, keyword case options, and compact mode — runs entirely in your browser.
Top comments (0)