Unformatted SQL is notoriously difficult to read and debug. A single query spread across one line may work perfectly, but it is nearly impossible to review in a code change, spot a bug in during an incident, or hand off to a colleague without confusion.
Why SQL formatting matters
Compare these two queries:
Unformatted:
select u.id,u.name,u.email,o.total from users u left join orders o on u.id=o.user_id where u.created_at>'2024-01-01' and o.status='paid' order by o.total desc limit 10
Formatted:
SELECT
u.id,
u.name,
u.email,
o.total
FROM users u
LEFT JOIN orders o
ON u.id = o.user_id
WHERE
u.created_at > '2024-01-01'
AND o.status = 'paid'
ORDER BY o.total DESC
LIMIT 10
The formatted version makes structure immediately visible — joins, filters, and ordering are each on their own lines. You can see at a glance that this query joins two tables, applies two filters, sorts descending, and pages results.
SQL formatting rules
Keyword casing
The SQL standard doesn't require uppercase keywords, but convention is to use UPPERCASE for reserved words (SELECT, FROM, WHERE, JOIN, AND) and lowercase for identifiers (table names, column names, aliases). This makes it easy to visually distinguish structure from data.
Indentation
Each clause (SELECT, FROM, WHERE, ORDER BY, GROUP BY, HAVING) starts at the same indent level. Continuation of the same clause is indented further. JOIN conditions (ON) are typically indented under their JOIN.
One item per line in SELECT
Each selected column gets its own line, especially when selecting more than three columns. This makes it easy to add, remove, or comment out individual columns during development and debugging.
WHERE conditions
Each condition in a WHERE clause should start with the logical operator (AND, OR) at the beginning of the line, not the end. Leading AND/OR makes it easier to comment out individual conditions.
-- Easy to comment out individual conditions:
WHERE
u.active = TRUE
AND u.role = 'admin'
-- AND u.created_at > '2024-01-01'
AND o.status = 'paid'
Aliases
Always alias joined tables to short, memorable names. Use the first letter or first two letters of the table name. Be consistent — use the same alias every time you reference the same table.
Dialect differences
Different databases have slightly different SQL syntax:
| Feature | MySQL | PostgreSQL | SQLite | T-SQL |
|---|---|---|---|---|
| String quotes | Single or double | Single only | Both | Single only |
| Identifier quotes | Backtick ` |
Double quote " |
Both | Square brackets [] |
| Auto-increment | AUTO_INCREMENT |
SERIAL / GENERATED |
AUTOINCREMENT |
IDENTITY |
| Boolean type | TINYINT(1) |
BOOLEAN |
INTEGER |
BIT |
| Pagination | LIMIT n OFFSET m |
LIMIT n OFFSET m |
LIMIT n OFFSET m |
OFFSET m ROWS FETCH NEXT n |
| String concat | CONCAT() or ` |
` | ` |
Common SQL anti-patterns
SELECT *
Avoid SELECT * in production queries. It selects all columns including ones you don't need, breaks when columns are added or reordered, prevents query optimizers from using covering indexes, and makes code harder to understand.
Implicit JOINs
The old-style comma JOIN syntax is harder to read and reason about:
-- Avoid:
SELECT * FROM users u, orders o WHERE u.id = o.user_id
-- Prefer:
SELECT * FROM users u
JOIN orders o ON u.id = o.user_id
Functions on indexed columns in WHERE
Wrapping an indexed column in a function prevents the query from using the index:
-- Index on created_at won't be used:
WHERE YEAR(created_at) = 2024
-- Index will be used:
WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01'
How to format SQL for free
- Go to SQL Formatter
- Paste your SQL query into the input panel
- Select your SQL dialect (MySQL, PostgreSQL, SQLite, T-SQL, BigQuery, Spark)
- Click Format or press Ctrl+Enter
- Copy the formatted output or download as .sql
The formatter supports all common SQL statements including SELECT, INSERT, UPDATE, DELETE, CREATE TABLE, and stored procedure definitions.