首頁 › 程式開發 › SQL 美化壓縮
🔧

SQL 美化壓縮

自寫詞法分析器排版 SQL:子句換行、JOIN 與 CASE 分層縮排、IN 超過閾值自動折行,壓成單行時把行註解改寫成區塊註解,字串裡的分號與括號不會誤傷

格式化选项
缩进 关键词 IN 折行阈值
美化保留全部注释并留在原来的位置;压成单行时行注释会改写成块注释,免得把后面的语句吃掉。
美化结果
词法说明
格式化只重排空白,不会改动字符串、注释、标识符里的内容:单引号与双引号字符串(含 '' 翻倍转义、反斜杠转义、 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 的差異用文字比對;建表語句裡的格式檢查規則用正規表示式測試試好再寫。