SQL 格式化

常见 SQL 方言格式化与压缩

正在加载工具…

关于 SQL 格式化与压缩

SQL 格式化与压缩工具会重新缩进查询,让连接、过滤条件和子查询对齐到各自所属的子句之下;当查询必须塞进字符串字面量或日志字段时,也可以折叠回单行。

SQL 的格式化对方言的敏感程度,远超普通文本重排。MySQL 的反引号、PostgreSQL 的美元符号引用体、SQL Server 的方括号标识符,以及各家特有的关键字,都会改变一个词法单元应当如何处理。选对与数据库匹配的方言,是「可靠重排」和「毁掉标识符」之间的分界线。

如何使用这个开发者工具

  1. 把查询、存储过程体或日志里的语句粘贴到输入区。
  2. 选择将要执行它的数据库方言,例如 MySQL、PostgreSQL 或 SQLite。
  3. 格式化后,从缩进读出子句结构:每个连接条件和过滤条件都应当落在自己的子句之下。
  4. 把输出中的带引号标识符和字符串字面量与原文逐一比对,这是格式化最容易扰动的部分。
  5. 把格式化后的查询复制进迁移脚本或评审;需要内嵌到代码里时改用压缩输出。

实例:一条读不下去的报表查询

从 ORM 日志里复制出来的查询是一整行。格式化让连接顺序和过滤位置显形,而这正是评审时真正需要看到的东西。

日志中的语句
select o.id,c.name,sum(i.qty*i.price) total from orders o join customers c on c.id=o.customer_id left join items i on i.order_id=o.id where o.created_at>='2026-01-01' and c.region in ('eu','uk') group by o.id,c.name having sum(i.qty*i.price)>1000 order by total desc limit 50
格式化结果
SELECT
  o.id,
  c.name,
  SUM(i.qty * i.price) total
FROM
  orders o
  JOIN customers c ON c.id = o.customer_id
  LEFT JOIN items i ON i.order_id = o.id
WHERE
  o.created_at >= '2026-01-01'
  AND c.region IN ('eu', 'uk')
GROUP BY
  o.id,
  c.name
HAVING
  SUM(i.qty * i.price) > 1000
ORDER BY
  total DESC
LIMIT
  50

子句一旦分层堆叠,LEFT JOIN 之后紧跟着对聚合值的 HAVING 就变得显眼:没有匹配明细的订单先被分组,再被 HAVING 过滤掉。这是一个正确性问题,而单行版本把它藏了起来。

影响格式化的方言差异

方言带引号标识符字符串字面量
MySQL / MariaDB`order`'text'(也允许双引号)
PostgreSQL"order"'text' 与 $$body$$
SQL Server / T-SQL[order]'text'、N'unicode'
SQLite"order" 或 [order]'text'
Oracle PL/SQL"ORDER"'text'、q'[text]'

常见问题排查

列名被转成大写,之后查询就失败了。

成因 在 PostgreSQL 中,不带引号的标识符会折叠为小写,而带引号的标识符区分大小写。改变带引号标识符的大小写,就等于改变了它指向的列。

解决办法 关闭关键字大小写转换,或确认格式化器没有动过带引号的标识符。逐个把输出中的引号名与原文比对。

美元符号引用的函数体被拆散了。

成因 PostgreSQL 中由 $$ 或 $tag$ 界定的函数体里是一整段嵌套程序。使用其他方言的格式化器不认识这个定界符,会把内部当作外层语句来排版。

解决办法 选择 PostgreSQL 方言。对较长的过程体,可以单独格式化函数体,再粘回定界符之间。

? 或 :name 之类的占位符被移动或删除了。

成因 参数标记因驱动而异。所选方言不认识的标记可能被当成运算符切分。

解决办法 先把参数替换成字面示例值再格式化,最后在成品中把标记还原回去。

格式化成功了,但查询返回的行不一样了。

成因 格式化器只重写空白和关键字大小写。结果若有差异,说明复制过程中有人手工改动过,最常见的是被截断的 IN 列表,或多语句粘贴时丢了一行。

解决办法 用文本比较工具,把格式化后的输出与「原文格式化后的副本」做差异对比,不要靠肉眼并排阅读两个版本。

适合用这个工具的场景

  • 在进入合并请求之前,把 ORM 生成或日志抓取的语句变成可评审的样子。
  • 统一迁移文件的缩进风格,让之后的差异只显示真正的改动。
  • 把别人写的报表查询读顺,读到能判断它的连接逻辑为止。
  • 把查询压成单行,便于内嵌到应用代码或 Shell 命令中。

应该换用别的工具的场景

  • 检查查询对你的库表是否合法。只有数据库能解析表名和列名。
  • 评估性能。请在真实数据库上用有代表性的数据执行 EXPLAIN。
  • 把查询改写成等价的另一种形式。格式化在设计上永远不改变语义。

隐私与数据处理

查询在当前浏览器标签页内完成词法分析与重新输出。它不会被执行,不会发送到数据库,也不会传输到我们的服务器。生产语句常常内嵌客户标识,日志形态下还带有字面参数值,因此粘贴不是你自己写的语句前,请先把它们替换成占位符。

相关开发者工具

常见问题

格式化会改变查询的行为吗?

不会。只有空白、换行,以及可选的关键字大小写发生变化。如果结果行为不同,说明两段文本另有差异,做一次 diff 就能看出在哪。

不确定方言时该选哪个?

选真正会执行这条语句的数据库。如果查询没有带引号的标识符、没有过程块、也没有厂商特有函数,多数方言的输出是一样的,选哪个都无所谓。

能一次格式化多条语句吗?

可以,用分号分隔的语句会依次格式化。内部含分号的过程块需要选对方言,格式化器才能把整块识别为一个单元。

为什么关键字被转成了大写?

关键字大写、标识符小写是流传最广的约定,因为它让子句边界一眼可辨。这纯粹是显示约定,在所有主流方言中 SQL 关键字都不区分大小写。

粘贴生产环境的查询安全吗?

文本本身留在你的浏览器里,但真正的风险是内容。日志语句常常带有邮箱、账号等字面值,请先替换成占位符。

压缩查询会让它跑得更快吗?

不会。无论哪种写法数据库都要解析语句,而解析耗时相对于计划生成和执行可以忽略。只有当查询必须放进不喜欢换行的地方时才需要压缩。