最近看到一個(gè)不錯(cuò)的 SQL 編程風(fēng)格指南:https://www.sqlstyle.guide/zh/僅供參考,最重要的是選擇一套方針并嚴(yán)格遵守它。一般原則應(yīng)該做的事情使用一致的、描述性的名稱。合理地使用空格和縮進(jìn)來(lái)增強(qiáng)可讀...
最近看到一個(gè)不錯(cuò)的 SQL 編程風(fēng)格指南:https://www.sqlstyle.guide/zh/
僅供參考,最重要的是選擇一套方針并嚴(yán)格遵守它。
一般原則
應(yīng)該做的事情
使用一致的、描述性的名稱。
合理地使用空格和縮進(jìn)來(lái)增強(qiáng)可讀性。
存儲(chǔ)符合 ISO-8601 標(biāo)準(zhǔn)的日期格式(YYYY-MM-DDTHH:MM:SS.SSSSS)。
為了提高可移植性,最好僅使用標(biāo)準(zhǔn) SQL 函數(shù)而不是特定供應(yīng)商的函數(shù)。
保證代碼簡(jiǎn)潔明了、沒(méi)有多余的 SQL —— 比如非必要的引號(hào)或括號(hào),或者可以推導(dǎo)出的 WHERE 子句。
必要時(shí)在 SQL 代碼中加入注釋。優(yōu)先使用 C 語(yǔ)言式的以 /* 開(kāi)始以 */ 結(jié)束的塊注釋,或使用以 -- 開(kāi)始的行注釋,并在末尾換行。
SELECT file_hash -- stored ssdeep hash FROM file_system WHERE file_name = '.vimrc';
/* Updating the file record after writing to the file */ UPDATE file_system SET file_modified_date = '1980-02-22 13:19:01.00000', file_size = 209732 WHERE file_name = '.vimrc';
應(yīng)避免的事情
駝峰命名法 —— 它不適合快速掃讀。
描述性的前綴或匈牙利命名法比如 sp_ 或 tbl。
復(fù)數(shù)形式 —— 盡量使用更自然的集合術(shù)語(yǔ)。比如,用“staff”替代“employees”,或用“people”替代“individuals”。
被引號(hào)包裹的標(biāo)識(shí)符(quoted identifier)—— 如果你必須使用這樣的標(biāo)識(shí)符,最好堅(jiān)持用 SQL92 的雙引號(hào)來(lái)提高可移植性(你可能需要配置你的 SQL 服務(wù)器以支持此特性,具體取決于供應(yīng)商)。
面向?qū)ο缶幊痰脑瓌t不該應(yīng)用到 SQL 或數(shù)據(jù)庫(kù)結(jié)構(gòu)上。
命名慣例
一般原則
保證名字獨(dú)一無(wú)二且不是保留字。
保證名字長(zhǎng)度不超過(guò) 30 個(gè)字節(jié) —— 實(shí)際上,如果你不使用多字節(jié)字符集,就是 30 個(gè)字符。
名字要以字母開(kāi)頭,不能以下劃線結(jié)尾。
只在名字中使用字母、數(shù)字和下劃線。
不要在名字中出現(xiàn)連續(xù)下劃線 —— 這樣很難辨認(rèn)。
在名字中需要空格的地方用下劃線代替(first name 變?yōu)?nbsp;first_name)。
盡量避免使用縮寫(xiě)詞。使用時(shí)一定確定這個(gè)縮寫(xiě)簡(jiǎn)明易懂。
SELECT first_name
FROM staff;
表名
使用集合名稱,或在不那么理想的情況下使用復(fù)數(shù)形式。如 staff(建議使用)和 employees。
不要使用類似 tbl 或其他的描述性的前綴或匈牙利命名法。
表不應(yīng)該同它的列同名,反之亦然。
盡量避免連接兩個(gè)表的名字作為關(guān)系表(relationship table)的名字。與其使用 cars_mechanics 做表名不如使用 services。
列名
總是使用單數(shù)形式。
避免直接使用 id 做表的主標(biāo)識(shí)符。
避免列名和表名同名,反之亦然。
總是使用小寫(xiě)字母,除非是特殊情況,如專有名詞。
別名與關(guān)聯(lián)名
別名應(yīng)該與它們所指的對(duì)象或表達(dá)式相關(guān)聯(lián)。
一般來(lái)說(shuō),關(guān)聯(lián)名應(yīng)該由對(duì)象名中每一個(gè)單詞的首字母組成。
如果已經(jīng)有相同的關(guān)聯(lián)名了,那么在關(guān)聯(lián)名后加一個(gè)數(shù)字。
總是加上 AS 關(guān)鍵字,因?yàn)檫@樣的明確聲明易于閱讀。
為計(jì)算出的數(shù)據(jù)(SUM() 或 AVG())命名時(shí),用一個(gè)將這條數(shù)據(jù)存在表中時(shí)會(huì)使用的列名。
SELECT first_name AS fn
FROM staff AS s1
JOIN students AS s2
ON s2.mentor_id = s1.staff_num;
SELECT SUM(s.monitor_tally) AS monitor_total
FROM staff AS s;
存儲(chǔ)過(guò)程名
名字一定要包含動(dòng)詞。
不要附加 sp_ 或任何其他這樣的描述性的前綴或使用匈牙利表示法。
統(tǒng)一的后綴
下列后綴有統(tǒng)一的意義,能保證 SQL 代碼更容易理解。在合適的時(shí)候使用正確的后綴。
_id —— 獨(dú)一無(wú)二的標(biāo)識(shí)符,如主鍵。
_status —— 標(biāo)志值或任何表示狀態(tài)的值,比如 publication_status。
_total —— 總和或某些值的和。
_num —— 表示該字段包含數(shù)值。
_name —— 表示名字,例如 first_name。
_seq —— 包含一系列值。
_date —— 表示該列包含日期。
_tally —— 計(jì)數(shù)值。
_size —— 大小,如文件大小或服裝大小。
_addr —— 地址,有形的或無(wú)形的,如 ip_addr
查詢語(yǔ)句
保留字
關(guān)鍵字總是大寫(xiě),如 SELECT 和 WHERE。
最好使用關(guān)鍵字的全稱而不是簡(jiǎn)寫(xiě),用 ABSOLUTE 而不用 ABS。
當(dāng)標(biāo)準(zhǔn) ANSI SQL 關(guān)鍵字能完成相同的事情時(shí),不要使用數(shù)據(jù)庫(kù)服務(wù)器特定的關(guān)鍵字,這樣能增強(qiáng)可移植性。
SELECT model_num
FROM phones AS p
WHERE p.release_date > '2014-09-30';
空白字符
正確地使用空白字符對(duì)清晰的代碼十分重要。不要把代碼堆在一起或移除自然語(yǔ)言中的空格。
空格
用空格使根關(guān)鍵字都結(jié)束在同一列上。在代碼中間形成一個(gè)從上到下的“川流”,這樣幫助讀者快速掃視代碼并將關(guān)鍵字和實(shí)現(xiàn)細(xì)節(jié)分開(kāi)。川流在排版時(shí)應(yīng)該避免,但是對(duì)閱讀 SQL 語(yǔ)句是有幫助的。
(SELECT f.species_name,
AVG(f.height) AS average_height, AVG(f.diameter) AS average_diameter
FROM flora AS f
WHERE f.species_name = 'Banksia'
OR f.species_name = 'Sheoak'
OR f.species_name = 'Wattle'
GROUP BY f.species_name, f.observation_date)
UNION ALL
(SELECT b.species_name,
AVG(b.height) AS average_height, AVG(b.diameter) AS average_diameter
FROM botanic_garden_flora AS b
WHERE b.species_name = 'Banksia'
OR b.species_name = 'Sheoak'
OR b.species_name = 'Wattle'
GROUP BY b.species_name, b.observation_date);
注意 SELECT 和 FROM 等關(guān)鍵字,都右對(duì)齊,而實(shí)際的列名和實(shí)現(xiàn)細(xì)節(jié)都左對(duì)齊。
注意下列情況總是加入空格:
在等號(hào)(=)前后
在逗號(hào)(,)后
成對(duì)的單引號(hào)(')前后,除非在括號(hào)中或后面是逗號(hào) / 分號(hào)
SELECT a.title, a.release_date, a.recording_date
FROM albums AS a
WHERE a.title = 'Charcoal Lane'
OR a.title = 'The New Danger';
換行
總是換行的情況:
在 AND 或 OR 前
在分號(hào)后(分隔語(yǔ)句以提高可讀性)
在每個(gè)關(guān)鍵字定義之后
將多個(gè)列組成一個(gè)邏輯組時(shí)的逗號(hào)后
將代碼分隔成相關(guān)聯(lián)的多個(gè)部分,幫助提高大段代碼的可讀性
讓所有的關(guān)鍵字右對(duì)齊、所有的值左對(duì)齊,這樣就能在查詢語(yǔ)句中間留出一個(gè)空隙,有助于快速掃讀整個(gè)查詢的定義。
INSERT INTO albums (title, release_date, recording_date)
VALUES ('Charcoal Lane', '1990-01-01 01:01:01.00000', '1990-01-01 01:01:01.00000'),
('The New Danger', '2008-01-01 01:01:01.00000', '1990-01-01 01:01:01.00000');
UPDATE albums
SET release_date = '1990-01-01 01:01:01.00000'
WHERE title = 'The New Danger';
SELECT a.title,
a.release_date, a.recording_date, a.production_date -- 將所有的日期放在一起
FROM albums AS a
WHERE a.title = 'Charcoal Lane'
OR a.title = 'The New Danger';
縮進(jìn)
為確保 SQL 的可讀性,一定要遵守下列規(guī)則。
Join 語(yǔ)句
Join 語(yǔ)句應(yīng)該縮進(jìn)到川流的另一側(cè)并在必要的時(shí)候添加一個(gè)換行。
SELECT r.last_name
FROM riders AS r
INNER JOIN bikes AS b
ON r.bike_vin_num = b.vin_num
AND b.engine_tally > 2
INNER JOIN crew AS c
ON r.crew_chief_last_name = c.last_name
AND c.chief = 'Y';
子查詢
子查詢應(yīng)該在川流的右側(cè)對(duì)齊并使用其他查詢相同的樣式。有時(shí)候?qū)⒂依ㄌ?hào)單獨(dú)置于一行并同與它配對(duì)的左括號(hào)對(duì)齊是有意義的 —— 尤其是當(dāng)存在嵌套子查詢的時(shí)候。
SELECT r.last_name,
(SELECT MAX(YEAR(championship_date))
FROM champions AS c
WHERE c.last_name = r.last_name
AND c.confirmed = 'Y') AS last_championship_year
FROM riders AS r
WHERE r.last_name IN
(SELECT c.last_name
FROM champions AS c
WHERE YEAR(championship_date) > '2008'
AND c.confirmed = 'Y');
推薦的形式
盡量使用 BETWEEN 而不是多個(gè) AND 語(yǔ)句。
同樣地,使用 IN() 而不是多個(gè) OR 語(yǔ)句。
當(dāng)數(shù)據(jù)輸出數(shù)據(jù)庫(kù)時(shí)需要處理時(shí),使用 CASE 表達(dá)式。CASE 語(yǔ)句能嵌套形成更復(fù)雜的邏輯結(jié)構(gòu)。
盡量避免 UNION 語(yǔ)句和臨時(shí)表。如果數(shù)據(jù)庫(kù)架構(gòu)能夠不靠這些語(yǔ)句運(yùn)行,那么多數(shù)情況下它就不應(yīng)該依靠這些語(yǔ)句。
SELECT CASE postcode
WHEN 'BN1' THEN 'Brighton'
WHEN 'EH1' THEN 'Edinburgh'
END AS city
FROM office_locations
WHERE country = 'United Kingdom'
AND opening_time BETWEEN 8 AND 9
AND postcode IN ('EH1', 'BN1', 'NN1', 'KW1');
創(chuàng)建語(yǔ)句
聲明模式信息時(shí)維護(hù)可讀代碼也很重要。所以列定義的順序和分組一定要有意義。
在 CREATE 定義中,每個(gè)列定義要縮進(jìn) 4 個(gè)空格。
選擇數(shù)據(jù)類型
盡量不使用供應(yīng)商相關(guān)的數(shù)據(jù)類型 —— 這些類型不可移植甚至有可能不能在相同供應(yīng)商的舊版本系統(tǒng)上使用。
只在真的需要浮點(diǎn)數(shù)運(yùn)算的時(shí)候才使用 REAL 和 FLOAT 類型,否則使用 NUMERIC 和 DECIMAL 類型。浮點(diǎn)數(shù)舍入誤差是個(gè)麻煩。
指定默認(rèn)類型
默認(rèn)值一定與列的類型相同 —— 如果一個(gè)列的類型是 DECIMAL 那么就不要使用 INTEGER 類型的值作為默認(rèn)值。
默認(rèn)值要緊跟類型聲明并在 NOT NULL 聲明前。
約束和鍵
約束和鍵是構(gòu)成數(shù)據(jù)庫(kù)系統(tǒng)的重要組成部分。它們能很快地變得難以閱讀和理解,所以遵從指導(dǎo)方針是很重要的。
選擇鍵
設(shè)計(jì)時(shí)應(yīng)該謹(jǐn)慎選擇構(gòu)成鍵的列,因?yàn)殒I會(huì)影響性能和數(shù)據(jù)完整性。
鍵在某種程度上應(yīng)該是獨(dú)一無(wú)二的。
該值在不同表中的類型應(yīng)該相同并且盡量不會(huì)更改。
該值能否通過(guò)某種標(biāo)準(zhǔn)格式(如 ISO 發(fā)布的標(biāo)準(zhǔn))?鼓勵(lì)與前面第二點(diǎn)一致。
盡量讓鍵保持簡(jiǎn)單,但在適當(dāng)情況下不要害怕使用復(fù)合鍵。
以上是定義數(shù)據(jù)庫(kù)時(shí)合乎邏輯的平衡做法。當(dāng)需求變更時(shí),鍵也應(yīng)該根據(jù)情況更新。
定義約束
確定鍵后,就可以用約束和字值段驗(yàn)證來(lái)定義它們。
概述
表至少需要一個(gè)鍵來(lái)保證其完整性和可用性。
除了 UNIQUE 、PRIMARY KEY 和 FOREIGN KEY 之外(數(shù)據(jù)庫(kù)供應(yīng)商會(huì)提供相應(yīng)的檢查),約束應(yīng)該有名字。
布局和順序
在 CREATE TABLE 語(yǔ)句后先定義主鍵。
約束的定義應(yīng)該緊跟它相應(yīng)的列的定義后。
如果該約束與多個(gè)列相關(guān),那么讓它離相關(guān)的列越近越好。實(shí)在不行就將它放在表定義的最后。
如果是應(yīng)用于整個(gè)表的表級(jí)別的約束,那么就將它放在表定義的最后。
按照字母順序安排定義,ON DELETE 排在 ON UPDATE 前。
有道理的話,把所有相關(guān)的語(yǔ)句對(duì)齊。比如,把所有 NOT NULL 定義對(duì)齊到同一列。這樣做并不難,但是能提高可讀性。
校驗(yàn)
當(dāng)字符串的格式已知時(shí),用 LIKE 和 SIMILAR TO 約束來(lái)保證它們的完整性。
當(dāng)數(shù)值的范圍可以確定時(shí),用范圍 CHECK() 來(lái)防止錯(cuò)誤的值進(jìn)入數(shù)據(jù)庫(kù)或在沒(méi)有提示的情況下截?cái)唷4蟛糠智闆r下至少要確認(rèn)數(shù)值大于零。
CHECK() 約束應(yīng)該在單獨(dú)的子句中以便 debug。
示例
CREATE TABLE staff (
PRIMARY KEY (staff_num),
staff_num INT(5) NOT NULL,
first_name VARCHAR(100) NOT NULL,
pens_in_drawer INT(2) NOT NULL,
CONSTRAINT pens_in_drawer_range
CHECK(pens_in_drawer BETWEEN 1 AND 99)
);
應(yīng)該避免的設(shè)計(jì)
在關(guān)系型數(shù)據(jù)庫(kù)的設(shè)計(jì)中應(yīng)用面向?qū)ο笤O(shè)計(jì)思想(原則)—— 面向?qū)ο笤O(shè)計(jì)思想(原則)并不能很好地適用于關(guān)系型數(shù)據(jù)庫(kù)的設(shè)計(jì),避免這個(gè)陷阱。
將值存入一列并將其單位存在另一列 —— 列的定義應(yīng)該讓自己的單位不言自明以避免在應(yīng)用內(nèi)進(jìn)行合并。使用 CHECK() 來(lái)保證插入的數(shù)據(jù)是合法的。
EAV (Entity Attribute Value) 表 —— 應(yīng)該用專門的產(chǎn)品來(lái)處理這樣的無(wú)模式數(shù)據(jù)。
因?yàn)槟承┰颍ㄈ鐬榱烁鶕?jù)時(shí)間歸檔、為了劃分跨國(guó)組織的區(qū)域)將本應(yīng)該放在一個(gè)表中的數(shù)據(jù)分到多個(gè)表中 —— 這樣的設(shè)計(jì)導(dǎo)致以后必須使用 UNION 操作而不能直接查詢一個(gè)表。
附錄
列的數(shù)據(jù)類型
出于在數(shù)據(jù)庫(kù)引擎之間達(dá)到最大程度兼容的目的,下面是一些建議使用的列數(shù)據(jù)類型。
字符型
CHAR
CLOB
VARCHAR
數(shù)值型
精確數(shù)值類型
BIGINT
DECIMAL
DECFLOAT
INTEGER
NUMERIC
SMALLINT
近似數(shù)值類型
DOUBLE PRECISION
FLOAT
REAL
日期時(shí)間類型
DATE
TIME
TIMESTAMP
二進(jìn)制類型
BINARY
BLOB
VARBINARY
其他類型
Boolean
INTERVAL
XML
原文來(lái)源:https://mp.weixin.qq.com/s/XOfjELbnQWDUdj1Tg3mndQ
來(lái)源:本文內(nèi)容搜集或轉(zhuǎn)自各大網(wǎng)絡(luò)平臺(tái),并已注明來(lái)源、出處,如果轉(zhuǎn)載侵犯您的版權(quán)或非授權(quán)發(fā)布,請(qǐng)聯(lián)系小編,我們會(huì)及時(shí)審核處理。
聲明:江蘇教育黃頁(yè)對(duì)文中觀點(diǎn)保持中立,對(duì)所包含內(nèi)容的準(zhǔn)確性、可靠性或者完整性不提供任何明示或暗示的保證,不對(duì)文章觀點(diǎn)負(fù)責(zé),僅作分享之用,文章版權(quán)及插圖屬于原作者。
Copyright©2013-2025 ?JSedu114 All Rights Reserved. 江蘇教育信息綜合發(fā)布查詢平臺(tái)保留所有權(quán)利
蘇公網(wǎng)安備32010402000125
蘇ICP備14051488號(hào)-3技術(shù)支持:南京博盛藍(lán)睿網(wǎng)絡(luò)科技有限公司
南京思必達(dá)教育科技有限公司版權(quán)所有 百度統(tǒng)計(jì)