SQL 美化壓縮
自寫詞法分析器排版 SQL:子句換行、JOIN 與 CASE 分層縮排、IN 超過閾值自動折行,壓成單行時把行註解改寫成區塊註解,字串裡的分號與括號不會誤傷
格式化选项
美化结果
词法说明
格式化只重排空白,不会改动字符串、注释、标识符里的内容:单引号与双引号字符串(含
两处按主流方言习惯取默认:反斜杠在引号字符串里一律当转义符(MySQL 默认行为);双引号内容按字符串着色,但整段原样输出, 所以 ANSI 的双引号标识符同样不会被改坏;
'' 翻倍转义、反斜杠转义、
E'…' / N'…' / X'…' / U&'…' 前缀、跨行字符串)、反引号
`带 空格`、方括号 [标识符]、-- 与 # 行注释、/* */
块注释、@@变量、:命名参数、? 占位符,以及 <>
!= >= || :: ->> ?.
这类多字运算符都能正确切分。两处按主流方言习惯取默认:反斜杠在引号字符串里一律当转义符(MySQL 默认行为);双引号内容按字符串着色,但整段原样输出, 所以 ANSI 的双引号标识符同样不会被改坏;
# 优先识别为 MySQL 行注释。括号不配对、引号或块注释没闭合时会给出大概位置并停止输出,
不会给出改坏一半的 SQL。
工具介紹
排版 SQL 的難點不在「加換行」,而在先弄清哪些字元屬於程式碼、哪些屬於內容。用正規表示式找關鍵字再插換行的做法,碰上 WHERE remark LIKE '%; SELECT 1' 這種字串,或者 -- 註解裡也寫了 FROM,就會把本來能跑的語句改壞。這個工具先做完整的詞法切分,再只對程式碼與程式碼之間的空白動手,字串、註解、識別字裡的內容一個字元都不改。
三種模式各管一件事
- 美化:子句換行加層級縮排,適合閱讀長報表 SQL、寫進設計文件、貼到工單裡給人看
- 壓縮:一條語句收成一行,適合塞進日誌、寫進設定檔與排程參數,或做 diff 前先把兩邊統一成同一形態;行註解會改寫成區塊註解,免得把後半句吃掉,也可以直接刪掉
- 只規範空白:保留你原本的行結構,只規整行內多餘空格與運算子兩側空格,改動最小,已經排好版的專案用它
美化模式的排版規則
- 頂層子句各佔一行:SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY、LIMIT、INSERT、UPDATE、SET、VALUES、WITH 等,多詞子句按整體辨識,不會出現
GROUP和BY被拆到兩行 - AND、OR、XOR 逐條換行:條件多的時候一螢幕能上下對齊比較,找漏寫的那個括號條件很快
- JOIN 家族分層:INNER、LEFT、RIGHT、FULL、CROSS、NATURAL 各起一行,ON 與 USING 的關聯條件縮排到下一層,多表連接不再是橫著一條長線
- CASE 逐行展開:WHEN、ELSE、END 各佔一行,且
END不會把後面的 SELECT 清單吃掉,這是很多線上格式化器排版CASE時最常出的錯 - IN 清單按閾值折行:元素數超過閾值(預設 6)時一行一個,沒超過就保持原樣;函式呼叫的括號、
OVER (...)視窗定義、VALUES 元組不會被拆散 - 子查詢與括號各加一層:CTE、EXISTS、衍生表的層級關係從縮排上直接讀得出來
- 語句之間空行分隔,統計行同時給出語句數、結果行數、最大縮排層級與輸入字元數
詞法層面不會碰的東西
- 字串:單引號與雙引號、連寫兩個單引號表示一個引號的轉義寫法、反斜線轉義、跨行字串,以及
E''、N''、X''、B''、U&''這些帶前綴的形式,內容整段原樣輸出 - 識別字:反引號
`帶 空格`、方括號[名稱]、雙引號識別字與中文列名都當一個整體,不會被切成關鍵字加殘片 - 註解:
--、#行註解與區塊註解留在原來的位置,行註解自帶換行,不會被併進程式碼行 - 參數與佔位符:
@@變數、:命名參數、?位置佔位不會被當成運算子處理 - 多字運算子:
>=<>!=||::->>?.保持為一個符號,不會被拆成兩個而改變語意 - 數字:科學記號、小數點開頭、十六進位字面量各自歸為一個完整的詞法單元
選項含義速查
| 選項 | 可選值 | 作用與差別 |
|---|---|---|
| 縮排 | 2 / 4 / 8 空格、Tab | 只改層級前綴寬度,不影響哪些行換行 |
| 關鍵字 | 大寫 / 小寫 / 保持原樣 | 只作用於辨識出的關鍵字與型別名,列名和表名的大小寫永不改動 |
| IN 折行閾值 | 1 至 99,預設 6 | 元素數超過它才一行一個,填 1 等於 IN 永遠折行 |
| 運算子兩側空格 | 開 / 關 | 控制等號、比較符周圍的空格,關掉更緊湊但難讀 |
| 逗號前置 | 開 / 關 | 逗號寫在行首,加欄位減欄位時版本 diff 更乾淨 |
| 壓縮時刪除註解 | 開 / 關 | 關掉時行註解改寫成區塊註解保留,打開則直接刪掉 |
常見問題
- 會不會把字串裡的分號當成語句結束?不會。只有在引號外、註解外的分號才作為語句邊界。範例 SQL 裡
';已取消; 備註'這種帶分號和括號的字串就是專門拿來驗證這一點的 - 括號不配對、引號沒閉合怎麼辦?頁面會報出大致位置(第幾行、第幾個字元)並停止輸出,不會給你一段改壞一半的 SQL。半套結果比直接報錯危險得多,因為它看起來像是能跑的
- 壓縮後的語句能直接執行嗎?能。字串與識別字原樣保留,變的只有空白;行註解被改寫成區塊註解或按選項刪掉,否則
--會把同一行後面的內容全吃掉 - 支援哪種方言?以 MySQL 與 PostgreSQL 的常見語法為主:反引號、方括號、帶前綴字串、
::型別轉換、視窗函式OVER、CTE 都能辨識。沒有實作$$美元引用與程序化腳本區塊,寫預存程序時那部分需要自己留意 - 表名恰好和關鍵字同名會被改動嗎?用反引號或雙引號把它包起來就一定是識別字。裸寫的名字如果與關鍵字同形且後面緊跟左括號,按函式呼叫處理,不會當成子句關鍵字換行
- 很大的 SQL 會不會卡?排版是單遍掃描,幾十萬字元也能秒級出結果。真正影響閱讀的是語句條數,可以用「拆分為多條」按語句分別檢視和複製
- 資料會上傳嗎?不會。分詞、排版、著色、複製、下載全部在頁面 JS 裡完成,不發任何請求,也沒有伺服器參與,內網離線打開照樣能用
- 美化模式和只規範空白模式差在哪?美化會重排換行與縮排;只規範空白不動你的換行位置,只把多餘空格和運算子空格規整一遍,適合團隊已有排版風格、只想清掉多餘空白的場景
排版完要嵌進程式碼的 SQL,字串拼接部分可以先用 JS 程式碼格式化規整;介面回傳的 JSON 用 JSON 格式化;批次整理欄位清單、加註解參考文字批次取代與文字行處理;對比兩份 SQL 的差異用文字比對;建表語句裡的格式檢查規則用正規表示式測試試好再寫。