SQL樣式指南 · SQL Style Guide

這篇文檔翻譯自以署名-相同方式共享 4.0 國際協議發佈的http://www.sqlstyle.guide,譯文以原文同樣的協議發佈。

Overview 綜述

你可以直接使用這些指導方針,或者fork後創建自己的版本——最重要的是選擇一套方針並嚴格遵守它。歡迎通過提交issue或pull request來提交建議或修復bug。

為了讓閱讀了Joe Celko的《SQL ProgrammingStyle》的團隊能更容易採用這套規則, 這套原則被設計成與該書的兼容的形式。該指南在某些領域嚴格一些,在另一些領域鬆懈一些。 當然該指南比Celko的書更簡潔一些,因為Celko的書包含了一些趣聞和每一條原則後的理由。

將該文檔的Markdown format格式添加到項目代碼庫中或將該頁面的鏈接發送給所有項目的參與者要比傳閱實體書容易得多。

Simon Holywell所著的《SQL樣式指南》以署名-相同方式共享 4.0 國際協議發佈,改編自http://www.sqlstyle.guide。

General 一般原則

Do 應該做的事情

使用一致的、敘述性的名稱。

靈活使用空格和縮進來增強可讀性。

存儲符合ISO-8601標準的日期格式(<code>YYYY-MM-DD HH:MM:SS.SSSSS/<code>)。

最好使用標準SQL函數而不是特定供應商的函數以提高可移植性。

保證代碼簡潔明瞭並消除多餘的SQL——比如非必要的引號或括號,或者可以推導出的多餘<code>WHERE/<code>語句。

必要時在SQL代碼中加入註釋。優先使用C語言式的以<code>/*/<code>開始以<code>*//<code>結束的塊註釋,或使用以<code>--/<code>開始的行註釋。


Avoid 應避免的事情

駝峰命名法——它不適合快速掃描。

描述性的前綴或匈牙利命名法比如<code>sp_/<code>或<code>tbl/<code>。

複數形式——儘量使用更自然的集合術語。比如,用“staff”替代“employees”,或用“people”替代“individuals”。

需要引用號的標識符——如果你必須使用這樣的標識符,最好堅持用SQL92的雙引號來提高可移植性。

面向對象編程的原則不該應用到結構化查詢語言或數據庫結構上。

Naming conventions 命名慣例

General 一般原則

保證名字獨一無二且不是保留字。

保證名字長度不超過30個字節。

名字要以字母開頭,不能以下劃線結尾。

只在名字中使用字母、數字和下劃線。

不要在名字中出現連續下劃線——這樣很難辨認。

在名字中需要空格的地方用下劃線代替。

儘量避免使用縮寫詞。使用時一定確定這個縮寫簡明易懂。

Tables 表名

用集群名稱,或在不那麼理想的情況下,複數形式。如<code>staff/<code>和<code>employees/<code>。

不要使用類似<code>tbl/<code>或其他的描述性的前綴或匈牙利命名法。

表不應該同它的列同名,反之亦然。

儘量避免連接兩個表的名字作為關係表(relationship table)的名字。與其使用<code>cars_mechanics/<code>做表名不如使用<code>services/<code>。

Columns 列名

總是使用單數形式。

避免直接使用<code>id/<code>做表的主標識符。

避免列名同表名同名,反之亦然。

總是使用小寫字母,除非是特殊情況,如專有名詞。

Aliasing or correlations 別名與關聯名

應該與它們別名的對象或與它們代表的表達式相關聯。

一般來說,關聯名應該是對象名的第一個字母。

如果已經有相同的關聯名了,那麼在關聯名後加一個數字。

總是加上<code>AS/<code>關鍵字,因為這樣的顯示聲明易於閱讀。

為計算出的數據命名時,用一個將這條數據存在表裡時會使用的列名。


Stored procedures 過程名

名字一定要包含動詞。

不要附加<code>sp_/<code>或任何其他這樣的敘述性前綴或使用匈牙利表示法。

Uniform suffix 統一的後綴

下列後綴有統一的意義,能保證SQL代碼更容易被理解。在合適的時候使用正確的後綴。

<code>_id/<code>獨一無二的標識符,如主鍵。

<code>_status/<code>標識值或任何表示狀態的值,比如<code>publication_status/<code>。

<code>_total/<code>總和或某些值的和。

<code>_num/<code>表示該域包含數值。

<code>_name/<code>表示名字。

<code>_seq/<code>包含一系列數值。

<code>_date/<code>表示該列包含日期。

<code>_tally/<code>計數值。

<code>_size/<code>大小,如文件大小或服裝大小。

<code>_addr/<code>地址,有形的或無形的,如<code>ip_addr/<code>

Query syntax 查詢語句

Reserved words 保留字

保留字總是大寫,如<code>SELECT/<code>和<code>WHERE/<code>。

最好使用保留字的全稱而不是簡寫,用<code>ABSOLUTE/<code>而不用<code>ABS/<code>。

當標準ANSI SQL關鍵字能完成相同的事情時,不要使用數據庫服務器相關的關鍵字,這樣能增強可移植性。

White space 空白字符

正確地使用空白字符對清晰的代碼十分重要。不要把代碼堆再一起或移除自然語言中的空格。

Spaces 空格

用空格使根關鍵字都結束在同一列上。在代碼中形成一個從上到下的“川流”,這樣幫助讀者快速掃描代碼並將關鍵字和實現細節分開。川流在排版時應該避免,但是對書寫SQL語句是有幫助的。

注意<code>WHERE/<code>和<code>FROM/<code>等關鍵字,都右對齊,而真實的列名都左對齊。

注意下列情況總是加入空格:

在等號前後(<code>=/<code>)

在逗號後(<code>,/<code>)

單引號前後(<code>'/<code>),除非單引號後面是括號、逗號或分號


Line spacing 換行

總是換行的情況:

在<code>AND/<code>或<code>OR/<code>前。

在分號後(分隔語句以提高可讀性)。

在每個關鍵詞定以後。

將多個列組成一個邏輯組時的逗號後。

將代碼分隔成相關聯的多個部分,幫助提高大段代碼的可讀性。

讓所有的關鍵字右對齊,讓所有的值左對齊,在查詢語句中間留出一個空隙。這樣能提高速讀代碼的速讀。

Identation 縮進

為確保SQL的可讀性,一定要遵守下列規則。

Joins Join語句

Join語句應該縮進到川流的另一側並在必要的時候添加一個換行。

Subqueries 子查詢

子查詢應該在川流的右側對齊並使用其他查詢相同的樣式。有時候將右括號單獨置於一行並同與它配對的左括號對齊是有意義的——尤其是當存在嵌套子查詢的時候。

Preferred formalisms 推薦的形式

儘量使用<code>BETWEEN/<code>而不是多個<code>AND/<code>語句。

同樣地,使用<code>IN/<code>而不是多個<code>OR/<code>語句。

當數據輸出數據庫時需要處理時,使用<code>CASE/<code>表達式。<code>CASE/<code>語句能嵌套形成更復雜的邏輯結構。

儘量避免<code>UNION/<code>語句和臨時表。如果數據庫架構能夠不靠這些語句運行,那麼多數情況下它就不應該依靠這些語句。

Create syntax 創建語句

聲明模式信息時維護可讀代碼也很重要。所以列定義的順序和分組一定要有意義。

在<code>CREATE/<code>定義中,每列要縮進4個空格。

Choosing data types 選擇數據類型

儘量不使用供應商相關的數據類型——這些類型可不能能在老系統上使用。

只在真的需要浮點數運算的時候才使用<code>REAL/<code>和<code>FLOAT/<code>類型,否則使用<code>NUMERIC/<code>和<code>DECIMAL/<code>類型。浮點數舍入誤差是個麻煩。

Specifying default values 指定默認類型

默認值一定與列的類型相同——如果一個列的類型是<code>DECIMAL/<code>那麼就不要使用<code>INTEGER/<code>類型作為默認值。

默認值要緊跟類型聲明並在<code>NOT /<code>聲明前。


約束和鍵

約束和鍵是構成數據庫系統的重要組成部分。它們能很快地變得難以閱讀和理解,所以遵從指導方針是很重要的。

Choosing keys 選擇鍵

設計時應該謹慎選擇構成鍵的列,因為鍵既明顯影響著性能和數據完整性。

鍵在某種程度上應該是獨一無二的。

該值在不同表中的類型應該相同並且儘量不會更改。

該值是否會無法通過某種標準格式(如ISO發佈的標準)?如

儘量讓鍵保持簡單,但在適當情況下不要害怕使用複合鍵。

以上是定義數據庫時合乎邏輯的平衡做法。當需求變更時,鍵也應該根據情況更新。

Defining constraints 定義約束

確定鍵後,就可以用約束和字值段驗證來定義它們。

General 概述

表至少需要一個鍵來保證其完整性和可用性。

約束應該有名字,除了<code>UNIQUE/<code>、<code>PRIMARY KEY/<code>和<code>FOREIGN KEY/<code>之外。

Layout and order 佈局和順序

在<code>CREATE TABLE/<code>語句後先定義主鍵。

約束的定義應該緊跟它相應的列的定義後。

如果該約束與多個列相關,那麼讓它儘量離與其相關的列距離越近越好。實在不行就講它放在表定義的最後。

如果是與整個表相關聯表級別的約束,那麼就將放在表的定義的最後。

按照字母順序安排定義,<code>ON DELETE/<code>排在<code>ON UPDATE/<code>前。

有道理的話,把所有相關的語句對齊。比如,把所有<code>NOT /<code>定義對齊到同一列。雖然這樣的做法有些慢,但是能提高可讀性。

Validation 校驗

用<code>LIKE/<code>和<code>SIMILAR TO/<code>約束來保證格式已知字符串的數據完整性。

當數字的值的範圍可以確定時,用<code>CHECK/<code>來防止錯誤的值進入數據庫或被錯誤地轉換。大部分情況下至少要確認值要大於零。

<code>CHECK/<code>約束應該在單獨的語句中以便debug。

Example<code>:/<code>

Design to avoid

面向對象設計思想並不適用於關係型數據庫——避免這個陷阱。

將值存入一列並將單位存在另一列。列的定義應該讓自己的單位不言自明以避免在應用內進行合併。使用<code>CHECK/<code>來保證數據庫中的數據是合法的。

EAV (Entity Attribute Value)表——用特殊的產品來處理無模式數據。

因為某些原因(如為了歸檔、為了劃分跨國公司的區域)將能合併在一起的表分開。這樣的設計導致以後必須使用<code>UNION/<code>操作而不能直接查詢一個表。