第三範式之上

說到範式,常常碰到的一個說法就是,數據庫設計知足第三範式就能夠了,足夠了。這個說法有時給人一種暗示,知足更高的範式是件複雜的事情,或至少是件繁瑣的事情,不必。數據庫

但實際上,不少模型一旦知足了第三範式,每每也已經知足了更高的範式。一些以第三範式爲標準設計的庫,極可能也已知足第四甚至第五範式,儘管它稱呼起來都是說知足了第三範式。數據庫設計

現實中的業務每每有着自身的規律與約束,一個庫模型,在知足第三範式時也知足了更高的範式,有時是一個很天然的事。相反,知足了第三範式但違反了更高的範式,這時候就要當心對待,這裏很容易發生設計錯誤。學習

在實際的操做中,高範式每每表明着更多的鏈接,有時爲了更好的響應速度、更便捷的某些操做,設計時會特地下降範式或違反範式。這種設計理念與本文的重點----「知足了第三範式但違反了更高的範式,這時候很容易發生設計錯誤」要注意區分開。spa

 

在繼續下文前,先回顧下前三個範式的概念:設計

第一範式,表的列(關係的屬性)是不可再分的,不能是複合的,每一列各自表示一個屬性。這個也是關係數據庫最基本的要求,不知足第一範式也就沒法說什麼關係的數據庫。
第二範式,在第一範式的基礎上,表中的每一行能夠被惟一地區分。
第三範式,知足第二範式,並在候選鍵上不存在傳遞依賴。代理

 

「一個設計知足了第三範式,但可能違反了更高範式」--這條警示何時該響起?如下諸狀況就是一些高危區:1.一個表是否與多個表關聯,特別是參與了多個多對多關係。2表包含着複合鍵。3使用的不是天然鍵而是代理鍵。blog

 

下面以一些容易出錯的關係表舉例:

1.知足第三範式,但不知足第四範式
數學

第四範式關注的是多值依賴。io

1.1 學生關係表基礎

學生關係表(學生,社團,課程)

顯然,學生能夠參加多個社團,也須要學習多個課程,這個表中社團屬性依賴於學生,課程屬性也依賴於學生,而後這2個屬性有多種組合數據,這違反了第四範式。
現實中社團與課程的組合意義不大,容易判斷。

以下面關係表的記錄。注意這裏爲方便描述給的是模擬記錄,實際中三個字段存的更多是id值而且是三個表的外鍵。

 

1.2 快遞送貨表

快速送貨表(快遞員,訂單,商品)

這裏快遞員按照訂單進行派送,將訂單上的全部商品送到顧客手上。
這種類型的模型也包含着多值依賴,而且這種模型一個高危的地方在於,每安排一個訂單,可能須要插入多條數據,如某訂單中包含3件商品,就必須插入三條數據。這裏的更新容易形成數據不當。

 該模型能夠分解爲2個關係表:

關係表1
(快遞員,訂單)

關係表2
(訂單,商品)

 

2. 知足第三範式,但違反第五範式
第五範式要求候選鍵能推導出全部鏈接依賴。

2.1 教學日程計劃表

教學日程計劃表(教室 ,教師 ,課程)

在這個模型中,教師有教學任務,課程安排在具體的教室進行。即便老師們個個都是全能,什麼課都能教,課程安排也要與教室類型匹配,生物課拿着待解剖的青蛙跑到鋼琴教室顯然不合適,現實中的老師也各有所長,雖然數學語文老師常來教體育課,但你應該不但願你的數學語文是體育老師教的。調侃的話很少說,這個模型裏有2個依賴:1.課程依賴教室的類型。2.教師依賴具體的課程。

以下教學日程計劃表模擬數據:

 

 

模型涉及的表以下:

教師表(TeacherID,Name)
教室表(RoomID,RoomName)
課目表(CourseID,CourseName)
教師任教表(TeacherID,CourseID)
教室科目表(RoomID,CourseID)
日程計劃表(TeacherID,CourseID,RoomID,StartTime,EndTime)

模型:



如上圖,日程計劃表中的三個外鍵TeacherID,CourseID,RoomID組成聯合主鍵,並分別關聯三個實體表Teacher,Course,Room。這種狀況沒法避免如上面(教學日程計劃表)模擬數據最後一條記錄,室內籃球館原本應該上體育課,但安排了生物實驗課,任課老師也發生錯誤安排了數學老師。

爲防止異常數據,模型能夠調整爲:

 

上圖並無改變表,只是改變了表之間的關係。最主要的變化是日程計劃表Schedule的外鍵關聯指向的是2張關係表TeacherCourse,RoomCourse。圖中發現Schedule的三個外鍵仍然和原來的同樣,若是對此有疑惑,不妨設想在關係表TeacherCourse,RoomCourse上各自設立代理主鍵key1,key2,此時Schedule的聯合主鍵就是(key1,key2)。不過在這個模型中,代理主鍵會屏蔽掉不少關鍵信息,鏈接時也無必要,所以使用3個鍵做聯合主鍵,但注意此時的鍵關係與原模型是不一樣的。


無損分解是一種分析是否違反較高範式的方法。當你有個大表,能夠把其中的某些字段分離出來做爲單獨的表,通過去重DISTINCT後作驅動表與原來的表進行左外鏈接 LEFT OUTER JOIN,若是獲得的結果沒有任何數據丟失,則原來的表可能違反了一些範式,須要檢查是否存在異常數據。當進行這樣的分析時,表中應該有足夠的數據,少許的數據不必定能知足判斷。



總結:1.大多數數據模型已經知足了高範式,明顯違反高範式時須要注意。2.多對多關係、複合鍵、代理鍵是容易出現違反高範式的地方。3.無損分解是一種有效的檢測方法。4.第六範式是將表的關係減小到只存在一個非關鍵屬性,這樣會致使表數量膨脹,但能夠避免空值列。第六範式的狀況不多,未在文中討論,放在這裏只是記錄一下。

相關文章
相關標籤/搜索