ORM 印出一段查詢,它以一行 300 字元的姿態落在你的 console 裡。格式化工具把那面文字牆變成有縮排、掃一眼就懂的查詢,每個子句各就各位。是同一段查詢——只是變得看得懂了。以下說明它實際在做什麼。
一長行進去,看得懂的查詢出來。 我們給SQL 格式化工具這一整行:
select u.id,u.name,count(o.id) as orders from users u left join orders o on o.user_id=u.id where u.active=1 group by u.id,u.name having count(o.id)>2 order by orders desc。回來的結果每個子句各佔一行、被選的欄位縮排在select底下,而最關鍵的是:它在=與>兩側補上了空白,所以o.user_id=u.id變成o.user_id = u.id。注意它沒有把關鍵字改成大寫:那是另一個獨立選項,因為大小寫是風格選擇,而縮排不是。
格式化改了什麼(又沒改什麼)
格式化只動空白、換行與縮排——以及選擇性的關鍵字大小寫。它把 SELECT、FROM、WHERE、JOIN、GROUP BY 各自放到獨立的行,把欄位和條件縮排,讓巢狀結構一目了然。
它從不更動的是:你的資料表、欄位、值與邏輯。格式化後的查詢和擠成一團時回傳完全相同的結果。這也代表格式化不是驗證——它不會告訴你某個欄位拼錯了,或這段查詢實際上跑不跑得動。
方言:工具為什麼要問你用哪個資料庫
SQL 有標準,但每家資料庫都加了自己的味道,格式化工具需要知道是哪一種才能正確解析:
- 識別字引號——MySQL 用反引號(
`col`);PostgreSQL 與標準 SQL 用雙引號("col")。 - 限制筆數——MySQL/SQLite/PostgreSQL 用
LIMIT,SQL Server 用TOP。 - 型別轉換——PostgreSQL 的
value::int在別處沒有對應寫法。
選錯方言,這些就會被誤判,縮排也會跑掉。貼進來前,先在 SQL 格式化選你實際用的資料庫。
關鍵字大寫:是風格,不是規則
很多團隊把關鍵字寫成大寫(SELECT、FROM),讓它們和資料表、欄位名區隔開。SQL 本身對關鍵字不分大小寫,所以這純粹是可讀性慣例——格式化工具可以一鍵把整段查詢統一過來。
大小寫是我們的 SQL 格式化工具刻意不動的東西。一句小寫的查詢,格式化後:
select
*
from
users
where
id = 1
同樣的形狀,用大寫打:
SELECT
id,
name
FROM
t
WHERE
a = 1
AND b = 2
小寫的 select 保持小寫;大寫的 SELECT 保持大寫。預設是 preserve,因為改關鍵字大小寫是團隊風格,不是修正錯誤 —— 而且悄悄改掉它會讓「純格式化」那個 commit 的 diff 變成沒辦法審,而那是格式化工具最不該做的一件事。
為什麼在本機做?
前端格式化工具在你的瀏覽器裡解析並重新輸出 SQL。你的查詢——往往透露了資料表結構與商業邏輯——永遠不會離開你的電腦。
相關工具
- 要清的是 JSON?用 JSON 格式化。
- 要把查詢結果在格式間轉換?試試 JSON ⇄ CSV ⇄ Excel。
格式化前後對照
同一段查詢,被 ORM 壓成一行後、再格式化的樣子:
select u.id,u.name,count(o.id) as orders from users u left join orders o on o.user_id=u.id where u.active=1 group by u.id,u.name having count(o.id)>0 order by orders desc;
格式化後,結構由上而下一目了然:
SELECT
u.id,
u.name,
COUNT(o.id) AS orders
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.active = 1
GROUP BY u.id, u.name
HAVING COUNT(o.id) > 0
ORDER BY orders DESC;
結果完全相同,但 JOIN、篩選、分組現在一眼就看得出來。
格式化真正會改的是換行落在哪裡。一個被壓成一行的 INSERT 回來是:
insert into
logs (a, b)
values
(1, 2)
子句關鍵字自己一行,它的運算元縮排在下面,而欄位清單的逗號留在行內。整個演算法就是這樣 —— 一行一個子句、運算元縮排 —— 一旦你能預測它,格式化過的檔案就能只靠形狀來審:一個沒有貼在最左邊的 WHERE,就是子查詢裡的 WHERE。
逗號放行尾還是行首
欄位常見兩種擺法:行尾逗號(每行結尾的 u.id,)或行首逗號(每行開頭的 , u.name)。行首逗號會讓版本控制的 diff 更乾淨——新增一個欄位只動一行,而不是兩行——但兩種都合法,多數格式化工具都可以選。同一個專案裡保持一致,比選哪一種更重要。
常見問題
- 格式化會影響效能嗎? 不會。解析器會忽略無意義的空白與關鍵字大小寫,所以格式化後的查詢對引擎而言完全等價。唯一對空白敏感的,是字串常值的內容。
- 格式化後的 SQL 該進版控嗎? 檢視表、遷移腳本、預存程序都建議這麼做——一致的風格能讓 diff 變小、審查更快。
- 但格式化不會修好壞掉的查詢。 它只是重排文字;要抓錯,還是得靠真正的資料庫或 linter。之後要把結果匯出?看如何把 JSON 轉成 CSV 與 Excel。