SQL格式化

这个工具做什么

把挤成一行的 SQL 拆成关键字大写, 按子句换行, 带缩进和语法高亮的可读形式. 它不改写你的语句, 只调整大小写与空白 -- 专门对付日志, 慢查询列表, MyBatis 映射文件里那种"一条 SQL 两千字符"的东西.

输入: select "where from" as x, count(*) c from t left join u on t.id=u.id group by x having c>1
输出:
SELECT
    "where from" AS x,
    count(*) c
FROM t
LEFT JOIN u ON t.id=u.id
GROUP BY x
HAVING
    c>1

注意 "where from" 是字符串常量, 里面的关键字原样保留, 不会被大写.

怎么用

  1. 把 SQL 粘进文本框(可以整段带 \n, 制表符, 注释一起粘进来, 提交前会先归一化空白);
  2. 点"格式化", 结果出现在下方并带高亮; 点"复制"取走纯文本;
  3. 上方标签页可以开多个: 新增, 关闭, 双击改名, 每个页各自保留一份输入和结果, "备注"输入框用来写这条 SQL 的说明. 适合对照同一条语句改写前后的样子.

什么情况会用到

  • 慢查询日志里抓出一行 SQL, 要人工判断走了哪个索引, 有没有隐式类型转换;
  • 把 EXPLAIN 要用的语句贴给同事, 需要先能看清结构;
  • 代码里拼接的动态 SQL(MyBatis 的 <if>, 字符串拼接)最终拼出来对不对, 靠格式化最容易看出来;
  • 数仓 ETL 里一条几百行的 INSERT ... SELECT, Review 之前先格式化一遍.

它做了哪些处理

  • 关键字(SELECT / FROM / WHERE / AND / OR / LEFT JOIN / GROUP BY / ORDER BY / HAVING / UNION / INSERT / VALUES / UPDATE / SET / DELETE 等)统一大写;
  • 子句各占一行: SELECT 的列表达式逐行 4 空格缩进, WHERE / HAVING 的条件也缩进; LEFT JOIN ... ON 保持在同一行;
  • 提交前把制表符换成空格, 把 ", 后面的空白压成一个空格, 所以多行输入也能正常处理;
  • 字符串常量, 标识符, 函数名, 运算表达式保持原样, 不会被改写.

常见问题

会不会改变 SQL 的语义?

格式化只处理大小写与空白, 不重排条件顺序也不加括号. 唯一需要留意的是关键字被大写: 如果你用了大小写敏感的库(例如 PostgreSQL 加双引号的标识符, 或某些字符集下的 MySQL 字符串比较), 别把改动后的语句直接拿去做精确匹配的数据操作, 先确认目标库的大小写规则.

提示"格式化异常"怎么办?

这是解析失败, 通常来自三件事: ① 语句本身语法不完整(被日志截断, 少了一个引号或括号); ② 粘贴时把前后的日志时间戳, ; 之外的内容一起带进来了; ③ 传的不是 SQL 而是别的文本. 先把首尾杂质去掉重试, 仍失败就手工补全引号括号再试.

支持 UPDATE / DELETE / 建表语句吗?

增删改查这类 DML 语句都能处理(实测 update t set a=1 where id=2 会拆成 UPDATE / SET / WHERE 三段). CREATE TABLE 这类 DDL 的列定义, 注释子句排版效果一般, 建议用数据库客户端的格式化功能.

SQL 很长会不会卡?

解析在服务端完成, 长语句主要慢在网络往返和结果渲染上, 不会像纯前端工具那样卡住页面. 特别长的语句(几百 KB)建议分段处理.

我的 SQL 会被怎么处理?

需要注意: 解析在服务端完成, 你的语句会作为请求参数发送到接口, 只用于这一次排版, 页面没有账号体系, 也不会把结果展示给其他访问者. 含真实业务数据, 密码或客户信息的语句请不要直接粘进来, 先把字面量替换成占位值.

相关工具