The conventions the formatter applies. Default indent is tabs (width 4); switch to spaces for editors like Databricks where the tab width differs. Programmatic use: the API ↗.
Reserved keywords, built-in functions and data types are lowercase (select, left join, row_number, isnull, decimal(20,2)). Identifiers — schema/table/column names — keep their original case.
Every clause keyword sits in a left column; its operand starts at a fixed tab stop (column 12), forming a vertical river. Keyword and first operand share a line.
select first_expression alias
,second_expression alias
from schema.table t
where 1=1
and t.flag = 1
List items break before the comma, aligned in the river column.
In a select list, aliases line up in a second column (no as). Outlier-long expressions keep a single-tab gap instead of dragging everyone right.
where 1=1Every where opens with 1=1; each real predicate is its own and/or line — trivially commentable and reorderable. Same for multi-condition on.
One blank line separates the select list, from, each join, where, group by… for an airy, scannable layout.
insert intoinsert into base.target (
col_a
,col_b)
select src.col_a col_a
,src.col_b col_b
from ...
update … set … fromAssignments use leading commas with the = signs aligned into their own column; from + joins + where 1=1 follow like a select.
case,(case
when x is null then -1
else 0
end) flag
Short windows stay inline; long ones explode, giving partition by/order by their own mini-river. Named windows in a window clause explode the same way.
,row_number() over (
partition by pa.customer_nrc
,pa.access_point_id
order by pa.promo_start_date asc) sorting_asc
with cte_count as (
select customer_id
,max(temp_order) max_order
from base.history
group by customer_id)
update base
set ...
Sections separated by an indented star-banner block comment.
No space after commas inside argument lists (isnull(x,0), in (5,6)); spaces around comparison/arithmetic operators; . binds tight.
mergemerge into / using are river lines; the on condition reads like a join; each when … then update / insert / delete is its own block. A subquery in using (…) is formatted recursively (see 17).
create table / alter tableInline column lists get leading commas with the type aligned into a column; data types are lowercased.
create or replace table z.t
(reference_month int
,plan_id decimal(20,0) not null
,plan_name varchar(100));
begin … end blocksCompound blocks are formatted, not passed through — the statements inside are indented one level (including a nested declare … handler … begin … end). begin transaction is left alone.
Derived tables in from/join, merge using (…), and nested subqueries at any depth format as a block: ( and ) on their own lines, inner query one indent deeper, alias after ).
from (
select a.id
,sum(a.v) tot
from base.a a
where 1=1
and a.flag = 1
) x
A script with several statements is split and each is formatted — separated by ; or just by a blank line (guarded so union, insert…select, CTEs and merge clauses are never cut apart).
Scope: query DML (select / insert / update / delete / merge), DDL (create / alter table), CTEs, case, window functions, subqueries and begin…end blocks. Other procedural wrappers (create/alter procedure, exec, use, go) are passed through untouched.