SQL 格式化的正确姿势(顺带说说方言差异)
从 ORM 日志里捞出来的 SQL 往往是一整行,排查问题时根本没法读。本文讲清楚格式化 SQL 的实用原则、关键字大小写的取舍,以及 MySQL 与 PostgreSQL 之间的方言差异。
从 ORM 或数据库慢日志里复制出来的 SQL,基本都是一整行:
select a.id,a.name,b.order_no,b.amount from users a left join orders b on a.id=b.user_id where b.status=1 and b.created_at>="2026-01-01" order by b.created_at desc limit 50;
这种 SQL 能执行,但不能读。粘进 SQL 格式化工具一键展开后,结构立刻清楚。
格式化的三条实用原则
一是子句各自成行。 SELECT / FROM / JOIN / WHERE / GROUP BY / ORDER BY / LIMIT 各占一行,缩进层级用来表达嵌套——子查询比外层多一级缩进。
二是 JOIN 的条件跟着 JOIN 走。 把 ON 紧贴对应的 JOIN,而不是全塞到 WHERE 里。虽然两种写法结果常常相同,但对 LEFT JOIN 而言语义完全不同:写进 WHERE 会把左连接变成内连接。
三是长 IN 列表考虑换行或改用临时表。 一个 IN 里塞 500 个字面量,格式化后会占满整屏,此时更好的做法是分批或建临时表。
关键字要不要大写
两种都有道理:大写关键字能让你一眼区分语法与字段名;小写则与 ORM 生成的风格一致、便于比对。
实战建议:团队内统一即可。格式化工具通常两件事都做得到(格式化与还原),配置一次就够。
方言差异会影响格式化结果
不同数据库的关键字集合不一样,如果工具猜错方言,LIMIT 旁边的分页语法可能被错误换行。常见差异:
- 分页:MySQL 用
LIMIT n, m;PostgreSQL 用LIMIT n OFFSET m;SQL Server 用OFFSET ... FETCH NEXT - 字符串拼接:MySQL 的
CONCAT()与 PostgreSQL 的|| - 标识符引用:MySQL 用反引号,PostgreSQL 用双引号
所以粘贴 SQL 时选对目标方言,格式化结果才符合预期。
顺便说压缩
SQL 不只有「展开」一种需求。要把 SQL 存进配置文件、塞进聊天窗口或写进代码常量时,反过来要压缩成一行。工具里的压缩功能做的就是这件事,同时保证不破坏字符串字面量内部的空白。