數據庫範式(1NF 2NF 3NF BCNF)詳解二

範式應用

 

我們來逐步搞定一個論壇的數據庫,有如下信息:

 

(1) 用戶:用戶名,email,主頁,電話,聯繫地址

 

(2) 帖子:發帖標題,發帖內容,回覆標題,回覆內容

 

第一次我們將數據庫設計爲僅僅存在表:

 

用戶名 email 主頁 電話 聯繫地址 發帖標題 發帖內容 回覆標題 回覆內容

 

這個數據庫表符合第一範式,但是沒有任何一組候選關鍵字能決定數據庫表的整行,唯一的關鍵字段用戶名也不能完全決定整個元組。我們需要增加"發帖ID"、"回覆ID"字段,即將表修改爲:

 

用戶名 email 主頁 電話 聯繫地址 發帖ID 發帖標題 發帖內容 回覆ID 回覆標題 回覆內容

 

這樣數據表中的關鍵字(用戶名,發帖ID,回覆ID)能決定整行:

 

(用戶名,發帖ID,回覆ID) → (email,主頁,電話,聯繫地址,發帖標題,發帖內容,回覆標題,回覆內容)

 

但是,這樣的設計不符合第二範式,因爲存在如下決定關係:

 

(用戶名) → (email,主頁,電話,聯繫地址)

 

(發帖ID) → (發帖標題,發帖內容)

 

(回覆ID) → (回覆標題,回覆內容)

 

即非關鍵字段部分函數依賴於候選關鍵字段,很明顯,這個設計會導致大量的數據冗餘和操作異常。

 

我們將數據庫表分解爲(帶下劃線的爲關鍵字):

 

(1) 用戶信息:用戶名,email,主頁,電話,聯繫地址

 

(2) 帖子信息:發帖ID,標題,內容

 

(3) 回覆信息:回覆ID,標題,內容

 

(4) 發貼:用戶名,發帖ID

 

(5) 回覆:發帖ID,回覆ID

 

這樣的設計是滿足第1、2、3範式和BCNF範式要求的,但是這樣的設計是不是最好的呢?

 

不一定。

 

觀察可知,第4項"發帖"中的"用戶名"和"發帖ID"之間是1:N的關係,因此我們可以把"發帖"合併到第2項的"帖子信息"中;第5項"回覆"中的"發帖ID"和"回覆ID"之間也是1:N的關係,因此我們可以把"回覆"合併到第3項的"回覆信息"中。這樣可以一定量地減少數據冗餘,新的設計爲:

 

(1) 用戶信息:用戶名,email,主頁,電話,聯繫地址

 

(2) 帖子信息:用戶名,發帖ID,標題,內容

 

(3) 回覆信息:發帖ID,回覆ID,標題,內容

 

數據庫表1顯然滿足所有範式的要求;

 

數據庫表2中存在非關鍵字段"標題"、"內容"對關鍵字段"發帖ID"的部分函數依賴,即不滿足第二範式的要求,但是這一設計並不會導致數據冗餘和操作異常;

 

數據庫表3中也存在非關鍵字段"標題"、"內容"對關鍵字段"回覆ID"的部分函數依賴,也不滿足第二範式的要求,但是與數據庫表2相似,這一設計也不會導致數據冗餘和操作異常。

 

由此可以看出,並不一定要強行滿足範式的要求,對於1:N關係,當1的一邊合併到N的那邊後,N的那邊就不再滿足第二範式了,但是這種設計反而比較好!

 

對於M:N的關係,不能將M一邊或N一邊合併到另一邊去,這樣會導致不符合範式要求,同時導致操作異常和數據冗餘。

對於1:1的關係,我們可以將左邊的1或者右邊的1合併到另一邊去,設計導致不符合範式要求,但是並不會導致操作異常和數據冗餘。

 

結論

 

滿足範式要求的數據庫設計是結構清晰的,同時可避免數據冗餘和操作異常。這並意味着不符合範式要求的設計一定是錯誤的,在數據庫表中存在1:1或1:N關係這種較特殊的情況下,合併導致的不符合範式要求反而是合理的。

 

在我們設計數據庫的時候,一定要時刻考慮範式的要求。


轉自:http://jacki6.iteye.com/blog/774889

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章