[{"data":1,"prerenderedAt":567},["ShallowReactive",2],{"guide-formatting-sql-in-code-reviews":3},{"id":4,"title":5,"body":6,"date":559,"description":560,"extension":561,"meta":562,"navigation":229,"path":563,"readingTime":239,"seo":564,"stem":565,"__hash__":566},"guides\u002Fguides\u002Fformatting-sql-in-code-reviews.md","Formatting SQL in Code Reviews",{"type":7,"value":8,"toc":546},"minimark",[9,13,18,21,24,47,51,54,59,171,174,178,181,185,195,260,263,374,381,385,388,464,467,471,474,508,512,529,533,542],[10,11,12],"p",{},"Unformatted SQL is one of the most common sources of friction in code reviews. A developer pastes a query written in a single line, a reviewer asks for better formatting, and the discussion spirals into personal preferences rather than meaningful feedback about logic and performance. Establishing clear SQL formatting standards eliminates this cycle and keeps reviews focused on what matters.",[14,15,17],"h2",{"id":16},"why-sql-formatting-deserves-its-own-standard","Why SQL Formatting Deserves Its Own Standard",[10,19,20],{},"Most teams enforce style guides for their primary programming language — linters catch missing semicolons, inconsistent quotes, and wrong indentation in JavaScript or Python. SQL, however, often lives outside those pipelines. It sits in migration files, ORM scopes, raw query strings, and analytics notebooks, bypassing the linter entirely.",[10,22,23],{},"Poorly formatted SQL creates real problems beyond aesthetics:",[25,26,27,35,41],"ul",{},[28,29,30,34],"li",{},[31,32,33],"strong",{},"Hidden bugs."," A missing comma in a SELECT list or an accidentally commented-out WHERE clause is much harder to spot in a wall of unformatted text.",[28,36,37,40],{},[31,38,39],{},"Review slowdown."," Reviewers spend cognitive bandwidth parsing layout instead of evaluating JOIN logic, index usage, or N+1 risks.",[28,42,43,46],{},[31,44,45],{},"Merge conflicts."," When multiple developers edit the same unformatted query without consistent line breaks, Git produces tangled conflicts that are painful to resolve.",[14,48,50],{"id":49},"setting-up-a-team-sql-style-guide","Setting Up a Team SQL Style Guide",[10,52,53],{},"A practical SQL style guide does not need to be exhaustive. Focus on the rules that have the highest impact on readability and review efficiency.",[55,56,58],"h3",{"id":57},"core-rules-to-define","Core Rules to Define",[60,61,62,78],"table",{},[63,64,65],"thead",{},[66,67,68,72,75],"tr",{},[69,70,71],"th",{},"Rule",[69,73,74],{},"Example",[69,76,77],{},"Why It Matters",[79,80,81,104,124,135,146,160],"tbody",{},[66,82,83,87,101],{},[84,85,86],"td",{},"Keyword casing",[84,88,89,93,94,93,97,100],{},[90,91,92],"code",{},"SELECT",", ",[90,95,96],{},"FROM",[90,98,99],{},"WHERE"," (uppercase)",[84,102,103],{},"Keywords stand out from identifiers",[66,105,106,109,121],{},[84,107,108],{},"Line breaks per clause",[84,110,111,112,93,115,93,117,120],{},"Each ",[90,113,114],{},"JOIN",[90,116,99],{},[90,118,119],{},"ORDER BY"," on a new line",[84,122,123],{},"Makes query structure scannable",[66,125,126,129,132],{},[84,127,128],{},"Indentation",[84,130,131],{},"4 spaces per nesting level",[84,133,134],{},"Shows subquery and CTE boundaries",[66,136,137,140,143],{},[84,138,139],{},"Comma placement",[84,141,142],{},"Trailing or leading — pick one",[84,144,145],{},"Consistency across all files",[66,147,148,151,157],{},[84,149,150],{},"Alias style",[84,152,153,156],{},[90,154,155],{},"AS"," keyword always, or never",[84,158,159],{},"Prevents ambiguous shorthand",[66,161,162,165,168],{},[84,163,164],{},"Semicolons",[84,166,167],{},"Always terminate statements",[84,169,170],{},"Required by some databases, avoids ambiguity",[10,172,173],{},"Document your choices in a short markdown file in the repository root. Reference it in pull request templates so authors can self-check before requesting review.",[14,175,177],{"id":176},"automating-formatting-checks-in-ci","Automating Formatting Checks in CI",[10,179,180],{},"Style guides that rely on manual enforcement inevitably drift. The most effective approach is to add a formatting check to your CI pipeline that fails the build on violations.",[55,182,184],{"id":183},"using-sqlfluff","Using sqlfluff",[10,186,187,190,191,194],{},[90,188,189],{},"sqlfluff"," is a dialect-aware SQL linter and formatter that supports PostgreSQL, MySQL, BigQuery, Snowflake, and more. Configure it with a ",[90,192,193],{},".sqlfluff"," file:",[196,197,202],"pre",{"className":198,"code":199,"language":200,"meta":201,"style":201},"language-ini shiki shiki-themes github-light github-dark","[sqlfluff]\ndialect = postgres\nexclude_rules = L034  # allow mixed select targets\n\n[sqlfluff:layout:type:comma]\nline_position = trailing\n\n[sqlfluff:layout:type:select_clause]\nline_position = leading\n","ini","",[90,203,204,212,218,224,231,237,243,248,254],{"__ignoreMap":201},[205,206,209],"span",{"class":207,"line":208},"line",1,[205,210,211],{},"[sqlfluff]\n",[205,213,215],{"class":207,"line":214},2,[205,216,217],{},"dialect = postgres\n",[205,219,221],{"class":207,"line":220},3,[205,222,223],{},"exclude_rules = L034  # allow mixed select targets\n",[205,225,227],{"class":207,"line":226},4,[205,228,230],{"emptyLinePlaceholder":229},true,"\n",[205,232,234],{"class":207,"line":233},5,[205,235,236],{},"[sqlfluff:layout:type:comma]\n",[205,238,240],{"class":207,"line":239},6,[205,241,242],{},"line_position = trailing\n",[205,244,246],{"class":207,"line":245},7,[205,247,230],{"emptyLinePlaceholder":229},[205,249,251],{"class":207,"line":250},8,[205,252,253],{},"[sqlfluff:layout:type:select_clause]\n",[205,255,257],{"class":207,"line":256},9,[205,258,259],{},"line_position = leading\n",[10,261,262],{},"Run it in CI:",[196,264,268],{"className":265,"code":266,"language":267,"meta":201,"style":201},"language-yaml shiki shiki-themes github-light github-dark","# .github\u002Fworkflows\u002Fsql-lint.yml\nname: SQL Lint\non: [pull_request]\njobs:\n  lint:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - run: pip install sqlfluff\n      - run: sqlfluff lint queries\u002F --dialect postgres\n","yaml",[90,269,270,276,290,305,313,320,330,337,350,362],{"__ignoreMap":201},[205,271,272],{"class":207,"line":208},[205,273,275],{"class":274},"sJ8bj","# .github\u002Fworkflows\u002Fsql-lint.yml\n",[205,277,278,282,286],{"class":207,"line":214},[205,279,281],{"class":280},"s9eBZ","name",[205,283,285],{"class":284},"sVt8B",": ",[205,287,289],{"class":288},"sZZnC","SQL Lint\n",[205,291,292,296,299,302],{"class":207,"line":220},[205,293,295],{"class":294},"sj4cs","on",[205,297,298],{"class":284},": [",[205,300,301],{"class":288},"pull_request",[205,303,304],{"class":284},"]\n",[205,306,307,310],{"class":207,"line":226},[205,308,309],{"class":280},"jobs",[205,311,312],{"class":284},":\n",[205,314,315,318],{"class":207,"line":233},[205,316,317],{"class":280},"  lint",[205,319,312],{"class":284},[205,321,322,325,327],{"class":207,"line":239},[205,323,324],{"class":280},"    runs-on",[205,326,285],{"class":284},[205,328,329],{"class":288},"ubuntu-latest\n",[205,331,332,335],{"class":207,"line":245},[205,333,334],{"class":280},"    steps",[205,336,312],{"class":284},[205,338,339,342,345,347],{"class":207,"line":250},[205,340,341],{"class":284},"      - ",[205,343,344],{"class":280},"uses",[205,346,285],{"class":284},[205,348,349],{"class":288},"actions\u002Fcheckout@v4\n",[205,351,352,354,357,359],{"class":207,"line":256},[205,353,341],{"class":284},[205,355,356],{"class":280},"run",[205,358,285],{"class":284},[205,360,361],{"class":288},"pip install sqlfluff\n",[205,363,365,367,369,371],{"class":207,"line":364},10,[205,366,341],{"class":284},[205,368,356],{"class":280},[205,370,285],{"class":284},[205,372,373],{"class":288},"sqlfluff lint queries\u002F --dialect postgres\n",[10,375,376,377,380],{},"For auto-fixing, use ",[90,378,379],{},"sqlfluff fix"," locally. In CI, keep it as a check-only step so developers are forced to run the fix command and review the changes before pushing.",[55,382,384],{"id":383},"pre-commit-hooks","Pre-commit Hooks",[10,386,387],{},"For faster feedback, add a pre-commit hook:",[196,389,391],{"className":265,"code":390,"language":267,"meta":201,"style":201},"# .pre-commit-config.yaml\nrepos:\n  - repo: https:\u002F\u002Fgithub.com\u002Fsqlfluff\u002Fsqlfluff\n    rev: 3.1.1\n    hooks:\n      - id: sqlfluff-fix\n        args: [--dialect, postgres]\n",[90,392,393,398,405,418,428,435,447],{"__ignoreMap":201},[205,394,395],{"class":207,"line":208},[205,396,397],{"class":274},"# .pre-commit-config.yaml\n",[205,399,400,403],{"class":207,"line":214},[205,401,402],{"class":280},"repos",[205,404,312],{"class":284},[205,406,407,410,413,415],{"class":207,"line":220},[205,408,409],{"class":284},"  - ",[205,411,412],{"class":280},"repo",[205,414,285],{"class":284},[205,416,417],{"class":288},"https:\u002F\u002Fgithub.com\u002Fsqlfluff\u002Fsqlfluff\n",[205,419,420,423,425],{"class":207,"line":226},[205,421,422],{"class":280},"    rev",[205,424,285],{"class":284},[205,426,427],{"class":294},"3.1.1\n",[205,429,430,433],{"class":207,"line":233},[205,431,432],{"class":280},"    hooks",[205,434,312],{"class":284},[205,436,437,439,442,444],{"class":207,"line":239},[205,438,341],{"class":284},[205,440,441],{"class":280},"id",[205,443,285],{"class":284},[205,445,446],{"class":288},"sqlfluff-fix\n",[205,448,449,452,454,457,459,462],{"class":207,"line":245},[205,450,451],{"class":280},"        args",[205,453,298],{"class":284},[205,455,456],{"class":288},"--dialect",[205,458,93],{"class":284},[205,460,461],{"class":288},"postgres",[205,463,304],{"class":284},[10,465,466],{},"This catches formatting issues before they even reach the remote repository, saving CI minutes and review rounds.",[14,468,470],{"id":469},"common-formatting-issues-to-watch-for","Common Formatting Issues to Watch For",[10,472,473],{},"Even with automation, certain patterns slip through and deserve explicit attention in reviews:",[25,475,476,489,496,502],{},[28,477,478,481,482,485,486,488],{},[31,479,480],{},"Implicit JOINs."," Queries that use comma-separated tables (",[90,483,484],{},"FROM users, orders",") instead of explicit ",[90,487,114],{}," syntax should be flagged. Explicit JOINs make the relationship between tables clear and reduce the risk of accidental cross joins.",[28,490,491,492,495],{},"**SELECT *",[31,493,494],{},"."," In production queries, wildcard selects should be justified. They break when columns are added or reordered and prevent covering indexes from working efficiently.",[28,497,498,501],{},[31,499,500],{},"Missing table aliases."," Ambiguous column references without table aliases cause errors in some databases and confusion in all of them.",[28,503,504,507],{},[31,505,506],{},"Over-nested subqueries."," CTEs (WITH clauses) improve readability over deeply nested subqueries. Encourage their use in the style guide.",[14,509,511],{"id":510},"key-takeaways","Key Takeaways",[25,513,514,517,520,526],{},[28,515,516],{},"Unformatted SQL wastes review time and hides logic bugs that structured formatting exposes immediately.",[28,518,519],{},"Define a minimal set of formatting rules — keyword casing, line breaks, indentation, comma placement — and document them in your repository.",[28,521,522,523,525],{},"Automate enforcement with a SQL linter like ",[90,524,189],{}," in CI and pre-commit hooks.",[28,527,528],{},"Use code reviews to catch semantic issues — implicit JOINs, SELECT *, and over-nested subqueries — rather than debating indentation preferences.",[14,530,532],{"id":531},"try-it-yourself","Try It Yourself",[10,534,535,536,541],{},"Need to clean up SQL before a review? Drop your raw queries into the ",[537,538,540],"a",{"href":539},"\u002Ftools\u002Fsql-formatter","SQL Formatter"," to apply consistent keyword casing, indentation, and line breaks in seconds.",[543,544,545],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":201,"searchDepth":214,"depth":214,"links":547},[548,549,552,556,557,558],{"id":16,"depth":214,"text":17},{"id":49,"depth":214,"text":50,"children":550},[551],{"id":57,"depth":220,"text":58},{"id":176,"depth":214,"text":177,"children":553},[554,555],{"id":183,"depth":220,"text":184},{"id":383,"depth":220,"text":384},{"id":469,"depth":214,"text":470},{"id":510,"depth":214,"text":511},{"id":531,"depth":214,"text":532},"2026-05-28","Establish SQL style standards for your team and catch formatting issues in pull requests.","md",{"immutable":229},"\u002Fguides\u002Fformatting-sql-in-code-reviews",{"title":5,"description":560},"guides\u002Fformatting-sql-in-code-reviews","BAghrmEWbKrNQLX8w_d2u2FC-mDvaS-Pz4IuVZ433UQ",1780401333985]