2012年2月6日 星期一

[SQL] 第三正規化 (3NF)

第三正規化(3NF,中國大陸譯作第三范式,台灣譯作第三正规化)是資料庫正規化中所使用的一種正規形式,用來檢驗是否所有非鍵屬性都只和候選鍵有相關性,也就是說所有非鍵屬性互相之間應該是無關的。
第三正規化和第二正規化不同的地方在於,在第三正規化裡,所有的非鍵屬性都必須和每個候選鍵有直接相關。如果再對第三正規化做進一步加強就成了BC正規化,它所強調的重點就在於 "資料間的關係是奠基在鍵上、以整個鍵為考量、而且除了鍵之外不考慮其他因素"。



以下面這個定義機械元件的關係為例:
機械元件
元件編號
(主鍵)
製造商名稱製造商位址
1000ToyotaPark Avenue
1001MitsubishiLincoln Street
1002ToyotaPark Avenue
本例中製造商位址很明顯地不該被列在這個關係裡面,因為和元件本身比起來,製造商位址應該和製造商比較有關係;正確的做法應該是把獨立成為一個新的資料表:
製造商
製造商名稱
(主鍵)
製造商位址
ToyotaPark Avenue
MitsubishiLincoln Street
然後把原本的資料表改成這樣:
機械元件
元件編號
(主鍵)
製造商名稱
1000Toyota
1001Mitsubishi
1002Toyota
先前那個資料表的問題在於每提到一次製造商名稱就要多存一次它的位址,而這就不符合第三正規化的原則。
下面提供了另一個例子:
訂單 (Order)
訂單編號 (Order Number)
(主鍵)
客戶名稱 (Customer Name)單價 (Unit Price)數量 (Quantity)小計 (Total)
1000David$35.003$105.00
1001Jim$25.002$50.00
1002Bob$25.003$75.00
在本例中,非主鍵欄位完全依賴於主鍵訂單編號,也就是說唯一的訂單編號能導出唯一非主鍵欄位值,符合第二正規化。第三正規化要求非主鍵欄位之間不能有依賴關系,顯然本例中小計依賴於非主鍵欄位單價和數量,不符合第三正規化。小計不應該放在這個資料表裡面,只要把單價乘上數量就可以得到小計了;如果想要符合第三正規化的話,就把小計拿掉吧 (不過在做查詢的時候,本來用 "SELECT Orders.Total FROM Order" 就要改成用 "SELECT UnitPrice * Quantity FROM Order" 了)。
訂單 (Order)
訂單編號 (Order Number)
(主鍵)
客戶名稱 (Customer Name)單價 (Unit Price)數量 (Quantity)
1000David$35.003
1001Jim$25.002
1002Bob$25.003

沒有留言:

張貼留言