SQL Formatter

Notepad++ plugin

Settings

Every SQL Formatter setting, explained with a real before/after example — no guessing what a checkbox does before you turn it on.

1. Dialect

Choose ANSI, Snowflake, PostgreSQL, MS SQL, MySQL, SQLite or Databricks. The formatter rewrites vendor-specific function names to the target dialect's equivalent and immediately applies an idiomatic casing preset (e.g. Snowflake = all caps, PostgreSQL = all lowercase).

Snowflake → MS SQL

NVL and LENGTH don't exist in T-SQL — the formatter knows the right alternative per dialect (ISNULL, LEN), not just one fixed translation.

Before

SELECT NVL(discount, 0), LENGTH(customer_name)
FROM orders

After

SELECT ISNULL(discount, 0), LEN(customer_name)
FROM orders

MS SQL → Snowflake

And the other way round: IIF, ISNULL and GETDATE() get their Snowflake equivalent, including the default casing that dialect uses.

Before

select iif(amount>1000,'large','small'), isnull(notes,'-'), getdate()
from orders

After

SELECT IFF(AMOUNT > 1000, 'LARGE', 'SMALL'), NVL(NOTES, '-'), CURRENT_TIMESTAMP
FROM ORDERS

2. Casing

Independently configurable for keywords, function names and identifiers (table and column names): Preserve, Lowercase or Uppercase. So you can have uppercase keywords without your column names changing along with them.

Keywords upper, functions upper, identifiers lower

A common combination: SQL keywords and functions stand out in uppercase, table and column names stay consistently lowercase.

Before

select Count(Order_Id), Customer_Name from Orders where Status = 'active'

After

SELECT COUNT(order_id), customer_name
  FROM orders
 WHERE status = 'active'

3. Columns & aliases

Put every SELECT column on its own line, choose whether the comma sits before or after the column name, and decide what happens to AS aliases: add, remove or leave as-is — with its own casing for the word AS itself.

Comma before + add AS (lowercase)

This plugin's default style: every column on its own line, comma at the start (so you spot it immediately while scrolling), and an implicit alias gets its AS back.

Before

SELECT order_id, SUM(amount) total, customer_name FROM orders

After

select order_id
     , sum(amount) as total
     , customer_name
  from orders

Comma after + remove AS

The classic style: comma at the end of the line, and AS gets stripped so the alias name sits directly after the expression.

Before

SELECT order_id, SUM(amount) AS total, customer_name FROM orders

After

select order_id,
       sum(amount) total,
       customer_name
  from orders

4. Alignment

This formatter's signature look: SELECT/FROM/WHERE right-aligned to each other's width (the classic 'staircase' style), and ON/AND inside a JOIN aligned under the end of the JOIN keyword.

Right-aligned keywords

select/from/where all share the same right edge, so the WHERE conditions start directly under the column names.

Before

SELECT order_id FROM orders WHERE status = 'active'

After

select order_id
  from orders
 where status = 'active'

ON aligned under JOIN

With multiple AND conditions in a JOIN, they line up neatly under each other instead of sitting flush against the left margin.

Before

SELECT * FROM orders o JOIN customers c ON c.customer_id = o.customer_id AND c.active = 1

After

select *
  from orders o
  join customers c
    on c.customer_id = o.customer_id
   and c.active = 1

5. Structure

How CASE statements, CTEs (WITH clauses), subqueries and semicolons get built up: every WHEN on its own line or kept compact, CTEs separated by a blank line, subqueries that indent relative to their own parent, and semicolons you can auto-add or strip away.

CASE: Expand vs. Inline

'Expand' puts every WHEN on its own line (readable with many branches); 'Inline' keeps everything on one line (compact for short CASEs).

Before

SELECT CASE WHEN amount > 1000 THEN 'large' WHEN amount > 100 THEN 'medium' ELSE 'small' END AS size FROM orders

After

select case
           when amount > 1000 then 'large'
           when amount > 100 then 'medium'
           else 'small'
       end as size
  from orders

CTEs: each on a new line + indented

With multiple CTEs in one WITH clause, each CTE gets its own block with a blank line in between, and the CTE's body indents under its name.

Before

WITH a AS (SELECT 1), b AS (SELECT 2) SELECT * FROM a, b

After

with a as (
         select 1
     )

   , b as (
         select 2
     )

select *
  from a
     , b

Auto-add semicolons

Handy for scripts with multiple statements: any statement still missing a semicolon gets one automatically — on the last line, its own line, or left as-is.

Before

SELECT 1 FROM t
SELECT 2 FROM t

After

select 1
  from t;

select 2
  from t;

6. Spacing

Spaces around operators (a = b vs a=b) and inside function parentheses (count( * ) vs count(*)), a blank line between clauses, how many blank lines survive between statements, a maximum line length, and automatically wrapping long IN (...) lists.

Operators: add spaces

a=b, a>b and a<>b all get spaces, without you having to write separate rules for every operator.

Before

SELECT * FROM orders WHERE amount>=100 AND status<>'cancelled'

After

select *
  from orders
 where amount >= 100
   and status <> 'cancelled'

Wrap long IN (...) lists

Set a character threshold; an IN list longer than that automatically wraps across multiple lines instead of one unreadable long line.

Before

SELECT * FROM orders WHERE status IN ('active', 'pending', 'processing', 'shipped', 'delivered')

After

select *
  from orders
 where status in ( 'active', 'pending', 'processing'
                  , 'shipped', 'delivered' )

7. JOINs

One switch: strip INNER and OUTER once they're redundant. INNER JOIN becomes JOIN, LEFT OUTER JOIN becomes LEFT JOIN — shorter, and functionally identical.

Strip INNER/OUTER

Before

SELECT * FROM orders o INNER JOIN customers c ON c.id = o.customer_id LEFT OUTER JOIN shippers s ON s.id = o.shipper_id

After

select *
  from orders o
  join customers c
    on c.id = o.customer_id
  left join shippers s
    on s.id = o.shipper_id

8. FQDN (fully qualified names)

Fill in a database and/or schema name, and every table reference in FROM/JOIN automatically gets that prefix — handy when you work across multiple databases/schemas and want to be explicit everywhere.

Add database + schema

Database = 'analytics', schema = 'public' — every unqualified table gets 'analytics.public.' prepended, aliases stay untouched.

Before

SELECT o.order_id FROM orders o JOIN customers c ON c.id = o.customer_id

After

select o.order_id
  from analytics.public.orders o
  join analytics.public.customers c
    on c.id = o.customer_id

9. Profiles

Save the complete combination of all settings above under a name ('team-style', 'client-x', ...), and switch between them with one click. Export as JSON to share with colleagues, or import a teammate's profile.

Extra: outside the Settings dialog

Three features you use straight from the menu, with nothing to configure first.

Convert Quotes

Switch between single, double and backtick quotes for strings and identifiers — handy when moving from MySQL to PostgreSQL.

Before

SELECT `customer_name` FROM `orders` WHERE `status` = "active"

After

SELECT 'customer_name' FROM 'orders' WHERE 'status' = 'active'

Convert number format

Convert Dutch notation (1.234,56) to English (1,234.56), or the other way round — avoids mistakes when re-typing report figures.

Before

SELECT * FROM orders WHERE amount > 1.234,56

After

SELECT * FROM orders WHERE amount > 1,234.56

dbt / Jinja & no-format pragma

{{ ref(...) }}, {{ var }} and {# comment #} are recognized and never split or re-cased. Want a block left completely untouched? Wrap it in -- @formatter:off / -- @formatter:on.

Before

select {{ ref('orders') }}.order_id
-- @formatter:off
from     weird_legacy_table   x
-- @formatter:on

After

select {{ ref('orders') }}.order_id
-- @formatter:off
from     weird_legacy_table   x
-- @formatter:on