杂记 › 技术笔记 › 6 个元素不折、7 个才折:SQL 美化与压缩对注释、关键字、IN 长列表和嵌套子查询各做了什么

6 个元素不折、7 个才折:SQL 美化与压缩对注释、关键字、IN 长列表和嵌套子查询各做了什么

一、压缩跑完,注释整段消失

一份跑了几个月的报表 SQL,输入 967 字符、14 行、3 条语句。按「美化」是 1376 字符、72 行,按「压缩」是 914 字符、3 行。体积确实下去了,贴在语句头部那两行说明字段口径的注释却一个字都不剩。

第二遍我先把「压缩时删除注释」的勾去掉再压。同一条 SELECT a -- 行注释 换行 FROM t,勾着时输出 15 字符 1 行,取消勾选才得到 24 字符的 SELECT a /* 行注释*/ FROM t。差的就是那个勾选框的默认状态——它默认勾着。

二、注释的落点有三种

站在语句外面的行注释留在原位:一段带头部说明的输入是 23 字符,美化后仍是 5 行 31 字符。站在括号里或 CASE 里的会被就地改写成块注释——输入 SELECT f(a -- 注 是 29 字符,输出 f(a /* 注*/) 的 38 字符,因为 -- 换成 /* */ 之后注释不再吞掉行尾;# 起头走同一条分支。

第三种才是压缩档:勾着时行注释和块注释一起被跳过,取消勾选才拿到上面那句 24 字符。列表页那句「压缩时把行注释改写成块注释」描述的是取消勾选之后的分支,不是默认分支。

三、IN 折行的判据是「严格大于」

阈值框默认 6,判据是「逗号数加 1 大于阈值」,等于不折:默认阈值下 6 个元素待在一行,第 7 个才炸开。输入框声明 1 到 99,代码只兜下界、不兜上界——同一条 20 元素的 IN,阈值填 99、100、999,输出完全一样,都是 6 行 111 字符。

100 个元素的列表,折与不折差得更远:

  • 折行:107 行、1238 字符,每个元素独占一行,行首是 8 个字符的前缀。
  • 把阈值改成 100 让它不折:6 行、432 字符。行数差 101,字符差 806。
  • 阈值填 1 不等于永远折行:2 个元素折成 9 行 68 字符,1 个元素的 IN 仍是 6 行 43 字符。
  • 带子查询的 IN 不看阈值:IN (SELECT b FROM u) 填 999 也展开成 11 行。
行数 107 行 6 行 字符数 1238 字符 432 字符 图 1:100 个元素折与不折

四、「只规范空白」这一档,6 个选项全不生效

它的实现直接拿 token 原文去拼,不读选项对象,而且只有压缩档会把选项条置灰。于是缩进、大小写、折行阈值、运算符空格、逗号前置、删除注释这 6 项在这里全是装饰:实测把「运算符两侧空格」关掉,输出仍是同一句 24 字符。

它也不补齐空格。x=1, y = 2, z= 3, w =4 进出都是 36 字符,只有多余空白被归一(26 字符缩成 18 字符),同一句换成「美化」是 7 行 60 字符。原来的行结构也保不住:行首缩进被抹光(43 字符那段出来 31 字符),空行被删(4 行 23 字符变 2 行 15 字符)。这一档只做了两件事——归一多余空白、清掉行首与空行。

五、改不改大小写,只看那两张词表

大小写只动 SQ_KW 的 174 个词和 SQ_FN 的 75 个函数名:myFun(1)、tab(a, b)、表名 TBL 原样不动,而 a::text 会被抬成 a::TEXT。决定换行的是 SQ_OWN 的 17 项、SQ_TAIL 的 16 项加上 SQ_JOIN 的 11 项,合成 44 个短语。

名单咬人两处。from 在关键字表里而不在函数表里,实测 SELECT from(1) 被当成子句换成 3 行、把 (1) 挂在 FROM 下面,「紧跟左括号就按函数调用处理」那句 FAQ 在这里不成立。压缩档也不读缩进、阈值、逗号前置与运算符空格,三种设置出来是同一行,大小写却照改,「压缩只动空白」同样不成立。

六、JOIN 的三词缺口,与乘算的缩进

SQ_JOIN 的 11 项里没有三词组合,NATURAL LEFT JOIN 落不进名单,被拆成 FROM、t1 NATURAL、LEFT JOIN t2 三段,NATURAL 留在 FROM 的内容行上,单写的 OUTER JOIN 同样认不出;LEFT OUTER JOIN(6 行、lvl=2、ON 再深一层)与 CROSS JOIN(5 行)都正常。

嵌套不是加一层而是乘一层:3 层派生表最深 lvl=5,缩进选 2、4、8 空格与 Tab 时,最深行前缀分别是 10、20、40、5 个字符,整段字符数 123、191、327、89,行数一直是 14。官方示例的最大缩进层级只有 3,套到第三层再选 8 空格,整段体积就翻倍以上。

2 空格 123 字符 前缀 10 4 空格 191 字符 前缀 20 8 空格 327 字符 前缀 40 Tab 89 字符 前缀 5 图 2:缩进乘算的体积代价

七、建表语句不排版,占位符紧贴等号会被切开

44 个短语里没有 CREATE TABLE、ALTER TABLE、CREATE INDEX、DROP TABLE:一份 6 行 4 列、86 字符的建表语句,美化后塌成 1 行 74 字符,不报错也不提示。PostgreSQL 的 $$ 引用更直接,SELECT $$ it's ok $$ 抛「' 引号没有闭合」。

更隐蔽的是占位符。WHERE b=? AND c=:uid AND d=@@global.x 里 @ 和 : 都算运算符字符,紧贴等号时被并成一个 token,空格再插回 token 内部,输出成 d =@@ global.x、c =: uid,变量名被劈成两段;等号前留一个空格就正常,59 字符那句出来是 8 行 79 字符。

八、同一份示例的四档成绩

档位结果字符数行数UTF-8 字节
输入原文967141101
美化1376721510
压缩91431048
只规范空白956141090

统计行是 5 项、含「结果字符数」,示例这一行实测是 3 / 72 / 1376 / 3 / 967。美化再美化逐字相同(1376 变 1376),压缩再压缩也相同,但压缩结果拿去美化会得 1378 字符、与直接美化差 2 字符——先压再美化不是原路返回。

量级不用担心:300135 字符、1819 条语句,美化用 164 毫秒得 49112 行、542060 字符,压缩用 82 毫秒得 292858 字符。全程不发请求、不写本地存储,因此没有历史记录、没有批量入口,只有 1 个输入框;下载在内容前加 U+FEFF,落盘文件比页面字符数多 3 字节。在 SQL 美化与压缩 的三档之间切换,要盯的是勾选框和阈值。

Q:压缩删掉的注释还能找回来吗?

只能取消「压缩时删除注释」的勾再压一次,拿到 /* */ 那种 24 字符写法;没有本地存储也没有历史,压掉的原文不在你手上就找不回来。美化档不吃注释,但括号与 CASE 内的行注释会被改成块注释,diff 变大。

Q:阈值是不是越小越折、越大越不折?

方向对,边界不对:判据是严格大于,1 个元素在阈值 1 下仍不折(6 行 43 字符);上界没有兜底,填 999 与填 99 一模一样;带子查询的 IN 与阈值无关,永远展开成 11 行。

Q:为什么同一条 SQL 两次排出来行数差这么多?

按三处排查:档位是否同一个、IN 阈值是否同一个、其中一次是否含子查询。剩下的差异来自缩进——8 空格与 Tab 之间,3 层嵌套下最深前缀从 40 个字符掉到 5 个。

📎 相关文章

后缀决定 MIME:同一份 70 字节 PNG 头改出 18 个后缀、13 种类型和 5 个未知 2026-10-23 转 JPG 时透明被强制填底色:91 个质量档位在 PNG 面前不参与编码 2026-10-23 「全部清除」后还剩 553 字节,「只去掉位置信息」连缩略图都没动 2026-10-23 序号位数只是下限、重名时 (2) 插在后缀之前:批量重命名 2000 个文件的实测口径 2026-10-23 证书指纹实测:1159 字节 DER 与 3 种摘要、4 种写法 2026-10-23