运维管理18 分钟阅读
SQLFluff:像 ESLint 一样规范你的 SQL 代码
SQL 代码没有统一规范?团队里每个人写的 SQL 风格都不一样?SQLFluff 是一款开源 SQL Linter,支持 20+ SQL 方言,可以像 ESLint 管理 JavaScript 一样管理 SQL 代码质量。本文从安装、配置到团队集成,手把手教你落地 SQL 规范体系。
2026年5月6日阅读—点赞—收藏—
mysqlpostgresql
在知识库中专注阅读,并随时返回相关工具与课程
SQL 代码没有统一规范?团队里每个人写的 SQL 风格都不一样?SQLFluff 是一款开源 SQL Linter,支持 20+ SQL 方言,可以像 ESLint 管理 JavaScript 一样管理 SQL 代码质量。本文从安装、配置到团队集成,手把手教你落地 SQL 规范体系。
做 DBA 或者后端开发的同学,一定经历过这样的场景:
SELECT * FROM USERS WHERE ID = 1select * from users where id = 1Select * From users Where id = 1代码审查的时候,大家与其讨论业务逻辑,不如先吵一架「到底关键字该不该大写」。
更严重的是,没有规范的 SQL 代码在维护时简直是噩梦。存储过程里面几百行的 SQL,缩进乱七八糟,别名随心所欲,JOIN 条件东一个西一个——别说别人了,就算是自己写的,三个月后再看也头疼。
前端有 ESLint、Prettier,后端有 Checkstyle、golint,那 SQL 呢?
答案就是 SQLFluff。
SQLFluff 是一个基于 Python 的开源 SQL Linter 和 Formatter,GitHub 上已经有 8000+ Star。它的核心能力:
支持的 SQL 方言非常多,包括但不限于:
简单说,不管你用什么数据库,SQLFluff 基本都能覆盖。
1# 基本安装23> **本章目标**:掌握本章核心知识点4> **前置要求**:完成前序章节学习5> **预计时长**:60 分钟67pip install sqlfluff89# 如果你用的是特定方言,可以安装对应插件10pip install sqlfluff-templater-dbt # dbt 用户1112# 验证安装13sqlfluff version1# 拉取官方镜像2docker pull sqlfluff/sqlfluff34# 使用 Docker 运行 lint5docker run --rm -v $(pwd):/sql sqlfluff/sqlfluff lint /sql/query.sql --dialect mysql1pipx install sqlfluff装完之后跑一下 sqlfluff version,能看到版本号就说明安装成功了。
假设我们有一个 query.sql 文件:
1select2 a.id,a.name,3 b.order_id,4 b.amount5from customers a6join orders b on a.id=b.customer_id7where a.status='active'8 and b.amount>100运行 lint 检查:
1sqlfluff lint query.sql --dialect mysql输出结果类似:
1== [query.sql] FAIL2L: 1 | P: 1 | LT01 | Expected only single space before 'select' keyword.3L: 1 | P: 1 | CP01 | Keywords must be upper case.4L: 2 | P: 9 | LT01 | Expected single space after comma.5L: 3 | P: 1 | LT02 | Incorrect indentation.6L: 6 | P: 1 | AL01 | Implicit/explicit aliasing of table.7L: 7 | P: 30 | LT01 | Expected single space before and after '='.8L: 8 | P: 17 | LT01 | Expected single space before and after '='.9L: 9 | P: 19 | LT01 | Expected single space before and after '>'.每一行告诉你:哪一行、哪个位置、违反了哪条规则、具体是什么问题。
1# 自动修复所有问题2sqlfluff fix query.sql --dialect mysql34# 只修复特定规则5sqlfluff fix query.sql --dialect mysql --rules CP01,LT0267# 交互模式,逐个确认8sqlfluff fix query.sql --dialect mysql --force修复后的 SQL 自动变成:
1SELECT2 a.id,3 a.name,4 b.order_id,5 b.amount6FROM customers AS a7JOIN orders AS b8 ON a.id = b.customer_id9WHERE10 a.status = 'active'11 AND b.amount > 100是不是瞬间清爽了很多?
1sqlfluff parse query.sql --dialect mysql这个命令会输出 SQL 的语法解析树,对调试自定义规则特别有用。你可以看到 SQLFluff 如何理解你的 SQL 结构——每一个关键字、标识符、操作符都会被解析成树形节点。
SQLFluff 的配置文件叫 .sqlfluff,放在项目根目录下。下面是一个实战中常用的配置:
1[sqlfluff]2# 选择你的 SQL 方言3dialect = mysql4# 模板引擎(如果用 Jinja2 或 dbt)5templater = raw6# 排除的规则7exclude_rules = AM04, RF028# 单行最大长度9max_line_length = 12010# 缩进单位11indent_unit = space1213[sqlfluff:indentation]14# 缩进大小15indent_unit = space16tab_space_size = 417indented_joins = false18indented_using_on = true1920[sqlfluff:rules:capitalisation.keywords]21# 关键字大写策略:upper / lower / capitalise / consistent22capitalisation_policy = upper2324[sqlfluff:rules:capitalisation.identifiers]25# 标识符(表名、列名)小写26extended_capitalisation_policy = lower2728[sqlfluff:rules:capitalisation.functions]29# 函数名大写30extended_capitalisation_policy = upper3132[sqlfluff:rules:capitalisation.literals]33# NULL, TRUE, FALSE 大写34capitalisation_policy = upper3536[sqlfluff:rules:aliasing.table]37# 表别名必须使用 AS 关键字38aliasing = explicit3940[sqlfluff:rules:aliasing.column]41# 列别名必须使用 AS 关键字42aliasing = explicit4344[sqlfluff:rules:aliasing.length]45# 别名最短长度46min_alias_length = 24748[sqlfluff:rules:convention.terminator]49# SQL 语句必须以分号结尾50multiline_newline = true51require_final_semicolon = true5253[sqlfluff:rules:layout.long_lines]54# 长行处理策略55ignore_comment_lines = true方言是最重要的配置项。不同的方言在语法细节上差异很大,比如 MySQL 的反引号、PostgreSQL 的 :: 类型转换、BigQuery 的反引号表名等。选错方言会导致误报。
1# MySQL2dialect = mysql34# PostgreSQL5dialect = postgres67# SQL Server8dialect = tsql910# Oracle11dialect = oracle1213# BigQuery14dialect = bigquery有些规则可能不适合你的团队,可以直接排除:
1# 在配置文件中排除2exclude_rules = AM04, LT05, RF0234# 或者在命令行排除5sqlfluff lint query.sql --exclude-rules AM04,LT05也可以在 SQL 文件中用注释临时禁用:
1-- noqa: CP012select * from users;34-- 禁用整行的所有规则5select * from users; -- noqa问题 SQL:
1select id, name from users where status = 'active';修复后:
1SELECT id, name FROM users WHERE status = 'active';配置:
1[sqlfluff:rules:capitalisation.keywords]2capitalisation_policy = upper这是最基础也是争议最多的规则。我的建议是:关键字统一大写,标识符统一小写,这是业界最常见的做法。
问题 SQL:
1SELECT UserId, UserName FROM Users;修复后:
1SELECT userid, username FROM users;这条规则确保表名和列名的大小写一致。注意,如果你的数据库是大小写敏感的(比如 PostgreSQL 默认行为),这条规则更加重要。
问题 SQL:
1SELECT2id,3 name,4 email5FROM6users7WHERE8 status = 'active';修复后:
1SELECT2 id,3 name,4 email5FROM6 users7WHERE8 status = 'active';统一的缩进让 SQL 的层次结构一目了然。
问题 SQL:
1SELECT u.id, o.amount2FROM users u3JOIN orders o ON u.id = o.user_id;修复后:
1SELECT u.id, o.amount2FROM users AS u3JOIN orders AS o ON u.id = o.user_id;显式的 AS 关键字让别名定义更清晰,不容易和其他语法混淆。
问题 SQL:
1SELECT2 COUNT(*) total_count,3 SUM(amount) total_amount4FROM orders;修复后:
1SELECT2 COUNT(*) AS total_count,3 SUM(amount) AS total_amount4FROM orders;问题 SQL:
1SELECT id,name,email FROM users WHERE id=1 AND status='active';修复后:
1SELECT id, name, email FROM users WHERE id = 1 AND status = 'active';操作符前后加空格,逗号后面加空格。这条规则对可读性提升巨大。
问题 SQL:
1SELECT id, name, email, phone, address, city, country FROM users;修复后:
1SELECT2 id,3 name,4 email,5 phone,6 address,7 city,8 country9FROM users;当选择多个列时,每个列单独一行,方便后续增删改和代码 diff 对比。
问题 SQL:
1SELECT * FROM users WHERE status = 'active';SQLFluff 会提示你避免使用 SELECT *,因为:
建议改为:
1SELECT id, name, email, status FROM users WHERE status = 'active';问题 SQL(某些方言下):
1SELECT2 department,3 COUNT(*) AS cnt4FROM employees5GROUP BY 1;修复后:
1SELECT2 department,3 COUNT(*) AS cnt4FROM employees5GROUP BY department;用列名代替位置编号,避免调整列顺序后 GROUP BY 出错。
问题 SQL:
1SELECT2 id3 , name4 , email5FROM users;修复后(根据配置可以是前置或后置):
1SELECT2 id,3 name,4 email5FROM users;前置逗号还是后置逗号,这又是一个经典的 holy war。SQLFluff 让你通过配置来统一团队标准,不用再吵了。
SQLFluff 最大的价值不在于个人使用,而在于团队统一。下面介绍几种主流的集成方式。
pre-commit 是 Python 生态最流行的 Git Hooks 管理工具。配合 SQLFluff,可以在每次提交前自动检查 SQL 文件。
首先安装 pre-commit:
1pip install pre-commit然后在项目根目录创建 .pre-commit-config.yaml:
1repos:2 - repo: https://github.com/sqlfluff/sqlfluff3 rev: 3.3.1 # 使用最新版本号4 hooks:5 - id: sqlfluff-lint6 name: sqlfluff-lint7 description: 'Lint SQL files with SQLFluff'8 # 指定额外参数9 args: ['--dialect', 'mysql']10 # 只检查 SQL 文件11 types: [sql]12 # 如果你还想自动修复,可以加上 fix hook13 - id: sqlfluff-fix14 name: sqlfluff-fix15 description: 'Fix SQL files with SQLFluff'16 args: ['--dialect', 'mysql', '--force']17 types: [sql]安装 hook:
1pre-commit install从此以后,每次 git commit 包含 .sql 文件时,SQLFluff 会自动检查。不通过的话,commit 会被拒绝,开发者必须修复后才能提交。
小技巧:如果项目中已有大量不规范的 SQL,可以先用
sqlfluff fix全量修复一次,提交一个「格式化」的 commit,再启用 pre-commit hook。
在 CI/CD 中集成 SQLFluff,可以确保 PR 中的 SQL 变更一定符合规范。
创建 .github/workflows/sqlfluff.yml:
1name: SQLFluff Lint23on:4 pull_request:5 paths:6 - '**/*.sql'7 - '.sqlfluff'89jobs:10 sqlfluff-lint:11 runs-on: ubuntu-latest12 steps:13 - name: Checkout code14 uses: actions/checkout@v41516 - name: Set up Python17 uses: actions/setup-python@v518 with:19 python-version: '3.11'2021 - name: Install SQLFluff22 run: pip install sqlfluff==3.3.12324 - name: Run SQLFluff Lint25 run: sqlfluff lint . --dialect mysql --format github-annotation2627 # 可选:将结果作为 PR 评论28 - name: Run SQLFluff Lint (详细输出)29 if: failure()30 run: sqlfluff lint . --dialect mysql --format human--format github-annotation 参数会让 lint 结果直接显示在 PR 的文件变更页面上,非常直观。
如果你用 GitLab CI,配置也类似:
1# .gitlab-ci.yml2sqlfluff-lint:3 image: python:3.11-slim4 stage: test5 before_script:6 - pip install sqlfluff==3.3.17 script:8 - sqlfluff lint . --dialect mysql9 only:10 changes:11 - '**/*.sql'12 - '.sqlfluff'安装 VS Code 扩展 SQLFluff(搜索 sqlfluff 即可找到),安装后可以获得:
在 VS Code 的 settings.json 中添加:
1{2 "sqlfluff.dialect": "mysql",3 "sqlfluff.linter.run": "onSave",4 "sqlfluff.format.enabled": true,5 "sqlfluff.executablePath": "sqlfluff",6 "editor.formatOnSave": true,7 "[sql]": {8 "editor.defaultFormatter": "dorzey.vscode-sqlfluff"9 }10}这样每次保存 .sql 文件时,SQLFluff 会自动格式化代码——体验和 Prettier 格式化 JavaScript 一样丝滑。
如果你用 DataGrip 或 IntelliJ IDEA,可以通过 External Tools 或 File Watchers 实现类似效果:
Settings > Tools > External Toolssqlflufffix $FilePath$ --dialect mysql --force$ProjectFileDir$SQLFluff 内置了 60+ 条规则,覆盖了绝大多数场景。但如果你的团队有特殊的编码规范,可以编写自定义规则。
大部分需求可以通过配置来实现,不需要写代码。比如:
1[sqlfluff]2# 组合使用多个配置来定义团队规范3dialect = mysql4max_line_length = 1005exclude_rules = AM04, RF02, ST0667[sqlfluff:rules:capitalisation.keywords]8capitalisation_policy = upper910[sqlfluff:rules:capitalisation.identifiers]11extended_capitalisation_policy = lower1213[sqlfluff:rules:aliasing.table]14aliasing = explicit1516[sqlfluff:rules:aliasing.column]17aliasing = explicit1819[sqlfluff:rules:convention.count_rows]20# 推荐使用 COUNT(*) 而不是 COUNT(1)21prefer_count_1 = false如果内置配置满足不了你,SQLFluff 支持用 Python 编写自定义规则插件。
创建一个规则插件 sqlfluff_custom_rules.py:
"""自定义 SQLFluff 规则示例。"""
from sqlfluff.core.rules import BaseRule, LintResult, RuleContext
class Rule_Custom_L001(BaseRule): """禁止在 WHERE 条件中使用函数包裹索引列。
1这条规则检查 WHERE 子句中是否对列使用了函数,2例如 WHERE YEAR(create_time) = 2026,3这样会导致索引失效。4"""56groups = ("all",)7name = "custom_l001"8description = "避免在 WHERE 条件中对列使用函数(可能导致索引失效)"910def _eval(self, context: RuleContext) -> LintResult | None:11 # 检查逻辑12 if context.segment.is_type("function"):13 parent = context.parent_stack[-1] if context.parent_stack else None14 if parent and parent.is_type("where_clause"):15 return LintResult(16 anchor=context.segment,17 description="WHERE 条件中对列使用函数可能导致索引失效,"18 "考虑改写 SQL 或使用函数索引。",19 )20 return None然后在 .sqlfluff 中引用:
1[sqlfluff]2plugin_host_install_path = /path/to/plugins当然,大多数团队用内置规则就够了。自定义规则更适合有特殊合规要求的金融、医疗等行业场景。
总结一下:
pgFormatter 够用sql-formatter(npm 包)更方便根据我在多个团队推行 SQL 规范的经验,以下是一些实用的建议:
不要指望一下子启用所有规则。推荐的节奏:
对于已有大量 SQL 文件的项目:
1# 1. 先全量修复2sqlfluff fix . --dialect mysql --force34# 2. 提交一个 formatting-only 的 commit5git add -A6git commit -m "style: 统一 SQL 代码格式(SQLFluff)"78# 3. 再启用 pre-commit hook9pre-commit install这样做的好处是,格式化相关的 git blame 都指向同一个 commit,不会污染正常的提交历史。
.sqlfluff 配置文件和 .pre-commit-config.yaml 一定要提交到 Git 仓库。这样团队所有成员用的是同一套规则,不会出现「在我机器上能通过」的问题。
对于实在改不动的历史存储过程,可以用 -- noqa 注释跳过:
1-- 历史遗留存储过程,暂不修改格式2-- noqa: disable=all3CREATE PROCEDURE legacy_proc()4BEGIN5 -- 这里面的代码不会被 SQLFluff 检查6 select * from old_table where Flag=1;7END;8-- noqa: enable=allSQLFluff 还在快速迭代中,新版本会修复 bug、新增规则、提升性能。建议每个季度更新一次版本,但更新前先在本地跑一遍全量 lint,确保新版本没有引入不兼容的变更。
1# 查看当前版本2sqlfluff version34# 升级到最新版5pip install --upgrade sqlfluff67# 升级后全量检查8sqlfluff lint . --dialect mysqlSQL 代码规范看起来是小事,但它直接影响团队协作效率和代码可维护性。SQLFluff 作为目前最完善的 SQL Linter,具备了落地 SQL 规范体系所需的一切:
与其每次 Code Review 的时候手动指出格式问题,不如让工具来做这件事。把精力省下来,花在真正重要的业务逻辑审查上。
如果你的团队还没有 SQL 规范,现在就是最好的开始时间。从 pip install sqlfluff 开始,一步步建立起你们的 SQL 代码质量体系吧。
参考链接:
- SQLFluff 官方文档:https://docs.sqlfluff.com/
- SQLFluff GitHub:https://github.com/sqlfluff/sqlfluff
- 规则完整列表:https://docs.sqlfluff.com/en/stable/rules.html
- Pre-commit 官网:https://pre-commit.com/