SQL Formatter & Beautifier
Format messy SQL queries with proper indentation and keyword uppercasing. Handles SELECT, INSERT, UPDATE, DELETE, CREATE TABLE, JOINs and subqueries.
The Code Review That Missed a Missing Join Condition
A representative, generic scenario that plays out in database-heavy teams: a query gets written under deadline pressure as a single unbroken line — select u.id,u.name,o.total from users u,orders o where u.status='active' — and gets pasted straight into a pull request. Written that way, the missing join predicate between users and orders is nearly invisible; the comma-join with no ON clause reads, at a glance, like a normal query, and a reviewer scanning a wall of unformatted SQL during a fast review approves it. In production, the query silently produces a cross join — every user row paired with every order row — multiplying result set size and slipping through as a "slow query" ticket days later rather than being caught immediately as an obvious bug. Once the same query is formatted, with FROM, the table list, and the missing ON condition each getting their own line, the absence of a join predicate becomes visually obvious in a way it never was as one dense line — this is the core, unglamorous argument for formatting SQL before it ever reaches a reviewer, not after a bug report.
How the Formatter Reads and Rewrites a Query
The tool works as a pure text transformation, not a SQL parser with a real grammar — it recognizes a fixed list of major clause keywords (SELECT, FROM, WHERE, the JOIN variants, GROUP BY, HAVING, ORDER BY, LIMIT, INSERT INTO, UPDATE, and others) and inserts a line break immediately before each one wherever it appears as a whole word in the input. Column lists following SELECT or SET are then indented one level, and AND/OR predicates inside a WHERE clause get the same indent so they read as a clearly subordinate list rather than running together with the clause keyword. When "Uppercase keywords" is enabled, every recognized keyword from a longer reference list is replaced with its canonical uppercase form via a case-insensitive regex substitution, regardless of how it was originally typed. None of this touches column names, table names, string literals, or operators — it operates purely on whitespace and keyword casing, which is exactly why the output is guaranteed to be semantically identical to the input.
Where Reformatting Earns Its Keep Day to Day
- Reviewing a migration file before merging it: Format a generated or hand-written migration query so a reviewer can see the full column list, join conditions, and WHERE predicates as a clear visual hierarchy instead of scanning one dense line for a subtle logic error.
- Investigating a slow query during an incident: Paste an ORM-generated query pulled from a slow-query log into the formatter first, so the JOIN chain and filter conditions are immediately visible before running
EXPLAIN ANALYZEto find the missing index. - Pasting a query into documentation: Format a query before embedding it in a runbook or README so it stays readable in a monospace code block without requiring horizontal scrolling.
- Onboarding a new team member onto an inherited schema: Reformat a complex, historically-accumulated query so its clause structure and subquery nesting are visible at a glance, rather than making a newcomer trace parentheses through one long line.
Why Reformatting Whitespace Can Never Change What a Query Returns
SQL, as standardized across the ANSI/ISO SQL specification and every major implementation (MySQL, PostgreSQL, SQLite, SQL Server), is a whitespace-insensitive grammar: the parser tokenizes a statement into keywords, identifiers, operators, and literals, and any amount of whitespace — including newlines — between two tokens is treated identically by the query planner. This is precisely why a formatter is safe to trust for readability without a second thought about correctness: it can only ever move where line breaks and indentation fall, never which tokens exist or in what order they appear, so the parsed query tree — and therefore the result set — is provably unchanged by anything a formatter does.
Formatting Errors That Look Like New Bugs But Aren't
- Mistaking a result-set difference for a formatting bug: If output rows differ after formatting, the underlying logic was already wrong — commonly a missing join condition the original single-line query obscured — formatting only made a pre-existing bug visible; it never introduces one.
- String literals containing keyword-like text: A WHERE clause filtering on a text column containing the literal word "from" inside a sentence can trip up a formatter that doesn't track quote boundaries carefully — always diff the formatted output against the original before committing it to a migration file.
- Formatting a template string instead of the final query: Pasting an application's raw template literal (with
${variable}placeholders) instead of the fully interpolated SQL gives the formatter incomplete keyword context and produces awkward indentation — paste the actual resolved query instead. - Assuming keyword casing changes are risky: Toggling uppercase keywords only changes the letter case of recognized SQL keywords, never identifiers — a column or table name that happens to match a keyword in lowercase, like a column literally named
from, is left untouched because it isn't used in keyword position.
Frequently Asked Questions
What SQL dialects does this formatter support?
The formatter handles standard SQL syntax common to all major relational databases: SELECT with column lists and aliases, FROM with table joins (LEFT, RIGHT, INNER, FULL, CROSS), WHERE predicates with AND and OR, GROUP BY, HAVING, ORDER BY, LIMIT and OFFSET, INSERT INTO with VALUES, UPDATE with SET, DELETE FROM, and CREATE TABLE. It works correctly with MySQL, PostgreSQL, SQLite, and SQL Server syntax since it operates purely on whitespace and keyword casing without interpreting dialect-specific extensions.
Does formatting change what my SQL query does?
No. The formatter only changes whitespace (spaces, newlines, indentation) and optionally the casing of SQL keywords. It never alters column names, table names, string literals, numeric literals, operators, or the logical structure of your query. SQL parsers treat any amount of whitespace between tokens identically, so a formatted query is semantically identical to the original and is safe to copy directly back into your database client, ORM raw query, or migration file.
Should I use a SQL formatter in a CI pipeline?
Yes — enforcing a consistent SQL style through pre-commit hooks or CI checks makes a measurable difference to code quality in database-heavy projects. When all migration files and raw query strings follow the same formatting convention, diffs are cleaner (a change to one column in a SELECT list affects one line, not the entire query), code review is faster, and subtle logic errors in JOIN conditions or WHERE predicates are easier to spot. Tools like sqlfluff (which supports multiple dialects and can auto-fix formatting) or pgFormatter can integrate directly into your Git pre-commit hook or CI workflow.