flashman
← All guides

Format SQL without mistaking a space for a rewrite

Format SQL in the default dialect and read the spacing: keyword case is preserved, unknown functions gain a space, and dollar-quoted strings are rejected.

2026-10-20 · 8 min read

  • sql
  • formatting
  • tooling

The SQL page formats with sql-formatter's default dialect and with no keywordCase option. The words you typed keep their case. Indentation, spaces around operators, and a space before some parentheses are the changes you should expect. A second style guide that uppercases SELECT is a different tool.

Use the page to read a query. Diff it against the migration before you treat every new space as an edit someone made by hand.

Learn which calls gain a space

A call the default dialect does not list is printed with a space before the parenthesis. now() becomes now (). foo(1) becomes foo (1). nvl(a,b) becomes nvl (a, b). ifnull(a,b) becomes ifnull (a, b). left(a, 2) becomes left (a, 2). date_trunc('day', t) becomes date_trunc ('day', t). NOW() becomes NOW (), so the case of the name survives and the space still appears.

Listed calls stay tight. count(*), count(), and count(1) stay tight. lower(name), cast(a as int), current_timestamp(), and COALESCE(a, b) stay tight. extract(day from t) and substring(a from 1 for 2) break onto several lines because of FROM, and the parenthesis still sits against the name.

  • Diff the formatted call against the call in source control.
  • Accept now () as the formatted spelling of now().
  • Accept count(*) with no inserted space.
  • Keep a database-specific formatter for dialects this page does not select.

Keep strings, comments, and case

Operators gain spaces: a=1 becomes a = 1, and in(1,2) becomes in (1, 2). A string is not a place where that rewrite runs. 'hello; world' stays one literal. 'it''s' keeps the doubled quote. A -- comment and a /* block */ stay, and a leading block comment is moved onto its own line. Two statements gain a blank line between them. The formatted text has no extra newline after the last character.

select stays select and SELECT stays SELECT. Mixed case inside COALESCE stays mixed. If a house style requires uppercase keywords, this page will not apply it, and a diff against an uppercased copy will show every keyword.

Stop at dollar quotes

select $tag$ hello; world $tag$ throws a parse error that begins Unexpected "$tag$ hell" and tells you the dialect is the default sql. The page cannot switch to postgresql. Rewrite the sample with ordinary quotes when you want indentation, and use a PostgreSQL-aware formatter when the dollar quotes are the point.

A box of only spaces returns an empty string and does not call the formatter. A query that is only a comment still formats. Copy copies the formatted text, including the space before an unknown call.

Review the statement the database will parse

Formatting does not execute SQL and does not bind parameters. A spaced call is still the same call to a parser that ignores whitespace. A dollar-quote error is a formatter limit, not a verdict on the database.

Use the SQL tool for this pass, diff for the migration text, the regex tester to find now( and count( in a larger file, and the JSON formatter when the query is stored as a string in a payload. Record the original call, the formatted call, and that the dialect was the default.

Try these tools