資料庫設計之設計表和欄位
資料庫設計技巧系列--設計表和欄位
設計表和欄位
1. 檢查各種變化
我在設計資料庫的時候會考慮到哪些資料欄位將來可能會發生變更。比方說,姓氏就是如此(注意是西方人的姓氏,比如女性結婚後從夫姓等)。所以,在建立系統儲存客戶資訊時,我傾向於在單獨的一個數據表裡儲存姓氏欄位,而且還附加起始日和終止日等欄位,這樣就可 以跟蹤這一資料條目的變化。
— Shropshire Lad
2. 採用有意義的欄位名
有一回我參加開發過一個專案,其中有從其他程式設計師那裡繼承的程式,那個程式設計師喜歡用螢幕上顯示資料指示用語命名欄位,這也不賴,但不幸的是,她還喜歡用一些奇怪的命名法,其命名採用了匈牙利命名和控制序號的組合形式,比如cbo1、 txt2、txt2_b 等等。
除非你在使用只面向你的縮寫欄位名的系統,否則請儘可能地把欄位描述的清楚些。當然,也別做過頭了,比如Customer_Shipping_Address_Street_Line_1 I 雖然很富有說明性,但沒人願意鍵入這麼長的名字,具體尺度就在你的把握中。
— Lamont Adams
3. 採用字首命名
如果多個表裡有好多同一型別的欄位(比如FirstName),你不妨用特定表的字首(比如
CusLastName)來幫助你標識欄位。
— notoriousDOG
時效性資料應包括“最近更新日期/時間”欄位。時間標記對查詢資料問題的原因、按日期重新處理/過載資料和清除舊資料特別有用。
— kol
5. 標準化和資料驅動
資料的標準化不僅方便了自己而且也方便了其他人。比方說,假如你的使用者介面要訪問外部資料來源(檔案、XML 文 檔、其他資料庫等),你不妨把相應的連線和路徑資訊儲存在使用者介面支援表裡。還有,如果使用者介面執行工作流之類的任務(傳送郵件、列印信箋、修改記錄狀態等),那麼產生工作流的資料也可以存放在資料庫裡。預先安排總需要付出努力,但如果這些過程採用資料驅動而非硬編碼的方式,那麼策略變更和維護都會方便得 多。事實上,如果過程是資料驅動的,你就可以把相當大的責任推給使用者,由使用者來維護自己的工作流過程。(但是會增加客戶的工作量,就看客戶是否配合了。一般情況下客戶是都不願意配合,因為誰也不愛幹活,所以只有自己多勞累或多招人來乾重復的簡單活)(軟體開發人員實際上是一個軟體設計的核心人員,因為整套軟體的設計理念都是由這個軟體開發人員來做決定的,做策略處理的。)
— tduvall
6. 標準化不能過頭
對那些不熟悉標準化一詞(normalization )的人而言,標準化可以保證表內的欄位都是最基礎的要素,而這一措施有助於消除資料庫中的資料冗餘。標準化有好幾種形式,但Third NormalForm(3NF)通常被認為在效能、擴充套件性和資料完整性方面達到了最好平衡。簡單來說,3NF 規定:
· 表內的每一個值都只能被表達一次。
· 表內的每一行都應該被唯一的標識(有唯一鍵)。
· 表內不應該儲存依賴於其他鍵的非鍵資訊。
遵守3NF 標準的資料庫具有以下特點:有一組表專門存放通過鍵連線起來的關聯資料。比方說,某個存放客戶及其有關定單的3NF 資料庫就可能有兩個表:Customer 和Order。Order 表不包含定單關聯客戶的任何資訊,但表內會存放一個鍵值,該鍵指向Customer 表裡包含該客戶資訊的那一行。更高層次的標準化也有,但更標準是否就一定更好呢?答案是不一定。事實上,對某些專案來說,甚至就連3NF 都可能給資料庫引入太高的複雜性。
— Lamont Adams
為了效率的緣故,對錶不進行標準化有時也是必要的,這樣的例子很多。曾經有個開發財務分析軟體的活就是用非標準化表把查詢時間從平均40 秒降低到了兩秒左右。雖然我不得不這麼做,但我絕不把資料表的非標準化當作當然的設計理念。而具體的操作不過是一種派生。所以如果表出了問題重新產生非標準化的表是完全可能的。
— epepke
7. Microsoft Access 報表技巧
如果你正在使用Microsoft Access,你可以用對使用者友好的欄位名來代替編號的名稱:比如用Customer Name 代替txtCNaM。這樣,當你用嚮導程式建立表單和報表時,其名字會讓那些不是程式設計師的人更容易閱讀。
— jwoodruf
8. 不活躍或者不採用的指示符
增加一個欄位表示所在記錄是否在業務中不再活躍挺有用的。不管是客戶、員工還是其他什麼人,這樣做都能有助於再執行查詢的時候過濾活躍或者不活躍狀態。同時還消除了新使用者在採用資料時所面臨的一些問題,比如,某些記錄可能不再為他們所用,再刪除的時候可以起到 一定的防範作用。
— theoden
9. 使用角色實體定義屬於某類別的列
在需要對屬於特定類別或者具有特定角色的事物做定義時,可以用角色實體來建立特定的時間關聯關係,從而可以實現自我文件化。
這裡的含義不是讓PERSON 實體帶有Title 欄位,而是說,為什麼不用PERSON 實體和
PERSON_TYPE 實體來描述人員呢?然後,比方說,當 John Smith, Engineer 提升為JohnSmith, Director 乃至最後爬到John Smith, CIO 的高位,而所有你要做的不過是改變兩個表PERSON 和PERSON_TYPE 之間關係的鍵值,同時增加一個日期/時間欄位來知道變化是何時發生的。這樣,你的PERSON_TYPE 表就包含了所有PERSON 的可能型別,比如Associate、Engineer、Director、CIO 或者CEO 等。
還有個替代辦法就是改變PERSON 記錄來反映新頭銜的變化,不過這樣一來在時間上無法跟蹤個人所處位置的具體時間。
— teburlew
10. 採用常用實體命名機構資料
組織資料的最簡單辦法就是採用常用名字,比如:PERSON、ORGANIZATION、ADDRESS 和PHONE 等等。當你把這些常用的一般名字組合起來或者建立特定的相應副實體時,你就得到了自己用的特殊版本。開始的時候採用一般術語的主要原因在於所有的具體使用者都能對抽象事物具體化。有了這些抽象表示,你就可以在第2 級標識中採用自己的特殊名稱,比如,PERSON 可能是Employee、Spouse、Patient、Client、Customer、Vendor 或者Teacher 等。同樣的,ORGANIZATION 也可能是MyCompany、MyDepartment、Competitor、Hospital、Warehouse、Government 等。最後ADDRESS 可以具體為Site、Location、Home、Work、Client、Vendor、Corporate 和FieldOffice 等。採用一般抽象術語來標識“事物”的類別可以讓你在關聯資料以滿足業務要求方面獲得巨大的靈活性,同時這樣做還可以顯著降低資料儲存所需的冗餘量。
— teburlew
11. 使用者來自世界各地
在設計用到網路或者具有其他國際特性的資料庫時,一定要記住大多數國家都有不同的欄位格式,比如郵政編碼等,有些國家,比如紐西蘭就沒有郵政編碼一說。
— billh
12. 資料重複需要採用分立的資料表
如果你發現自己在重複輸入資料,請建立新表和新的關係。
— Alan Rash
13. 每個表中都應該新增的3 個有用的欄位
· dRecordCreationDate,在VB 下預設是Now(),而在SQL Server 下預設為GETDATE()
· sRecordCreator,在SQL Server 下預設為NOT NULL DEFAULT USER
· nRecordVersion,記錄的版本標記;有助於準確說明記錄中出現null 資料或者丟失資料的原因
— Peter Ritchie
14. 對地址和電話採用多個欄位
描述街道地址就短短一行記錄是不夠的。Address_Line1、Address_Line2 和Address_Line3 可以提供更大的靈活性。還有,電話號碼和郵件地址最好擁有自己的資料表,其間具有自身的型別和標記類別。
— dwnerd
過分標準化可要小心,這樣做可能會導致效能上出現問題。雖然地址和電話表分離通常可以達到最佳狀態,但是如果需要經常訪問這類資訊,或許在其父表中存放“首選”資訊(比如
Customer 等)更為妥當些。非標準化和加速訪問之間的妥協是有一定意義的。
— dhattrem
15. 使用多個名稱欄位
我覺得很吃驚,許多人在資料庫裡就給 name 留一個欄位。我覺得只有剛入門的開發人員才會這麼做,但實際上網上這種做法非常普遍。我建議應該把姓氏和名字當作兩個欄位來處理,然後在查詢的時候再把他們組合起來。
— klempan
Klempan 不是唯一一個注意到使用單個name 字 段的人,要把這種情況變得對使用者更為友好有好些方法。我最常用的是在同一表中建立一個計算列,通過它可以自動地連線標準化後的欄位,這樣資料變動的時候它也跟著變。不過,這樣做在採用建模軟體時得很機靈才行。總之,採用連線欄位的方式可以有效的隔離使用者應用和開發人員介面。
— damon
16. 提防大小寫混用的物件名和特殊字元
過去最令我惱火的事情之一就是資料庫裡有大小寫混用的物件名,比如CustomerData。這一問題從Access 到Oracle 資料庫都存在。我不喜歡採用這種大小寫混用的物件命名方法,結果還不得不手工修改名字。想想看,這種資料庫/應用程式能混到採用更強大資料庫的那一天嗎?採用全部大寫而且包含下劃符的名字具有更好的可讀性(CUSTOMER_DATA),絕對不要在物件名的字元之間留空格。
— bfren
17. 小心保留詞
要保證你的欄位名沒有和保留詞、資料庫系統或者常用訪問方法衝突,比如,最近我編寫的一個ODBC 連線程式裡有個表,其中就用了DESC 作為說明欄位名。後果可想而知!DESC 是DESCENDING 縮寫後的保留詞。表裡的一個SELECT *語句倒是能用,但我得到的卻是一大堆毫無用處的資訊。
— Daniel Jordan
18. 保持欄位名和型別的一致性
在命名欄位併為其指定資料型別的時候一定要保證一致性。假如欄位在某個表中叫做
“agreement_number”,你就別在另一個表裡把名字改成“ref1”。假如資料型別在一個表裡是整數,那在另一個表裡可就別變成字元型了。記住,你幹完自己的活了,其他人還要用你的資料庫呢。
— setanta
19. 仔細選擇數字型別
在SQL 中使用smallint 和tinyint 型別要特別小心,比如,假如你想看看月銷售總額,你的總額欄位型別是smallint,那麼,如果總額超過了$32,767 你就不能進行計算操作了。
— egermain
20. 刪除標記
在表中包含一個“刪除標記”欄位,這樣就可以把行標記為刪除。在關係資料庫裡不要單獨刪除某一行;最好採用清除資料程式而且要仔細維護索引整體性。
— kol
21. 避免使用觸發器
觸發器的功能通常可以用其他方式實現。在除錯程式時觸發器可能成為干擾。假如你確實需要採用觸發器,你最好集中對它文件化。
— kol
22. 包含版本機制(但是多新增欄位會增加程式設計的難度和修改程式的風險)
建議你在資料庫中引入版本控制機制來確定使用中的資料庫的版本。無論如何你都要實現這一要求。時間一長,使用者的需求總是會改變的。最終可能會要求修改資料庫結構。雖然你可以通過檢查新欄位或者索引來確定資料庫結構的版本,但我發現把版本資訊直接存放到資料庫中 不更為方便嗎?。
— Richard Foster
23. 給文字欄位留足餘量
ID 型別的文字欄位,比如客戶ID 或定單號等等都應該設定得比一般想象更大,因為時間不長你多半就會因為要新增額外的字元而難堪不已。比方說,假設你的客戶ID 為10 位數長。那你應該把資料庫表字段的長度設為12 或者13 個字元長。這算浪費空間嗎?是有一點,但也沒你想象的那麼多:一個欄位加長3 個字元在有1 百萬條記錄,再加上一點索引的情況下才不過讓整個資料庫多佔據3MB 的空間。但這額外佔據的空間卻無需將來重構整個資料庫就可以實現資料庫規模的增長了。
— tlundin
24. 列命名技巧
我們發現,假如你給每個表的列名都採用統一的字首,那麼在編寫SQL 表示式的時候會得到大大的簡化。這樣做也確實有缺點,比如破壞了自動錶連線工具的作用,後者把公共列名同某些資料庫聯絡起來,不過就連這些工具有時不也連線錯誤嘛。舉個簡單的例子,假設有兩個表:
Customer 和Order。Customer 表的字首是cu_,所以該表內的子段名如下:cu_name_id、
cu_surname、cu_initials 和cu_address 等。Order 表的字首是or_,所以子段名是:
or_order_id、or_cust_name_id、or_quantity 和or_description 等。
這樣從資料庫中選出全部資料的SQL 語句可以寫成如下所示:
Select * from Customer, Order
Where cu_surname = "MYNAME"
and cu_name_id = or_cust_name_id
and or_quantity = 1;
在沒有這些字首的情況下則寫成這個樣子:
Select * from Customer, Order
Where Customer.surname = "MYNAME"
and Customer.name_id = Order.cust_name_id
and Order.quantity = 1
第1 個SQL 語句沒少鍵入多少字元。但如果查詢涉及到5 個表乃至更多的列你就知道這個技巧多有用了。
— Bryce Stenberg