不同人有不同的 coding style,但為了保持整體專案的一致性,我們會建立一些原則,確保大家的程式碼有一定程度的共通性。
SQL 其實有蠻多流派,像是 BigQuery 中,按下快捷鍵 Ctrl + Shift + F 就可以進行格式化,而它是採用所有保留字都全為大寫的風格,換行斷句也有些自己的規則。
source: https://www.reddit.com/r/ProgrammerHumor/comments/la0s1m/sql_programmer/
其實早在我發現大小寫不影響執行時,我就懶得用大寫了,看很多影片教學等,發現不少外國人會用大寫寫一整個單字或一段文字,WHICH 我覺得蠻增加我的認知負荷的,都要多一咪咪力氣才能看懂。在 dbt 的文件中,基本上是全小寫的,令人心安。
因為有蠻多不同的規則,雖然有蠻多 extension 可以一鍵排版,但其結果都並非我喜歡的,也不太容易自己做修正。
pre-commit,一套監督大家的程式碼有沒有長一樣的檢查工具,應該有蠻多人介紹過的。
而相較於其他的程式語言,SQL 雖然比較沒有這樣的資源,不過幸好是有 sqlfluff 這個工具可以使用。
(不知道是不是寫 SQL 的人比較沒有在在乎這件事情,還是不會做這件事?)
在部署這個工具的時候,跟想像中有落差的是,在初期需要花力氣去檢視其中的規則。
如方才上述內容,我們有一些規則跟預設的並不相同。
隨便舉一些例子,像是最後一個欄位後是否要有結尾的逗號、group by 可以接受欄位名稱、數字、還是 all?
以下是它預設的設定與範例
Anti-pattern
select
a,
b,
from foo
Best practice
select
a,
b
from foo
但我自己其實傾向使用它視作 anti-pattern 的樣式。因為若當我們要加上一個 c 欄位時,它只要在下方再加上一個 c,
、而不是在前一行加上逗號後,在下一行再加上 c。
這個的差別會體現於 PR review 中,一個變動一行、一個變動兩行,但這個變動所做的事情,需要被 review 的其實只是新增的那個欄位,b 是沒有變動的,雖然微小,但積少成多。
SQLfluff 會預設如此,是因為有些資料倉儲中,加上結尾的逗號是 syntax error,只能如此設計。
講到這邊就順便小抱怨一下,BigQuery 在 select 時可以加上句尾逗號,但 group by 與 order by 不行,實在不喜歡不一致的感覺。
Anti-pattern
A mix of implicit and explicit column references are used in a GROUP BY
clause.
SELECT
foo,
bar,
sum(baz) AS sum_value
FROM fake_table
GROUP BY
foo, 2;
Best practice
Reference all GROUP BY
/ORDER BY
columns either by name or by position.
-- GROUP BY: Explicit
SELECT
foo,
bar,
sum(baz) AS sum_value
FROM fake_table
GROUP BY
foo, bar;
-- GROUP BY: Implicit
SELECT
foo,
bar,
sum(baz) AS sum_value
FROM fake_table
GROUP BY
1, 2;
不知道有沒有人以前沒看過這兩種寫法(現在是都看過了)
我在突然要查一些資訊,這樣一次性的 SQL code 中,絕對是寫數字,有夠方便,不過有人會覺得寫數字太過於抽象,這就看團隊要怎麼找出一個共識。
不過交錯使用(上面的 Anti-pattern)、以及數字是不連續的(e.g. 1,2,3,5,8)應該是普世禁止的。
另外近期 BigQuery 推出了新的語法 group by all(官方文件),它可以直接將 aggregate / window functions 以外的欄位做 grouping,十分方便(懶惰)的新功能。
而這個語法在 SQLfluff 中似乎還沒有支援,因此若要使用這個語法,就必須透過一些旁門左道來避開,像是將所有 group by 的檢查取消掉,或是在該行後面加上後綴以避開檢查。
還有不少其他的案例,在這邊簡單提兩個,文件中規則百百種,任君挑選。
蠻令人慶幸的是,SQLfluff 有支援 dbt 的 templater!(文件)
因為 dbt 的 sql file 中,並非純粹的 sql code,有 jinja 語法會混入一些奇怪的語言,如果按照一般的 sql formatter,不只無法將 jinja 部分格式化,還會報錯。
不過這個 templater 也有缺點,這是比較近期才開發的,且功能較多,檢查起來也比較費時費力,文件中都有打一些預防針了,我們現在遇到的問題就是,在本地開發時,時常跑半天跑不出結果,或許應該要遵循官方的建議,改用 jinja templater 看看,之後有空來做這件事情,再跟大家分享。
補充:在撰寫本篇時,發現有人開發了 pre-commit 的 dbt 版本(如文件),名為 dbt-checkpoint,看起來持續在維運中,後續再來試試看是不是更合用。