說到正規化,經常碰到的乙個說法就是,資料庫設計滿足第三正規化就可以了,足夠了。這個說法有時給人一種暗示,滿足更高的正規化是件複雜的事情,或至少是件繁瑣的事情,沒必要。
但實際上,很多模型一旦滿足了第三正規化,往往也已經滿足了更高的正規化。一些以第三正規化為標準設計的庫,很可能也已滿足第四甚至第五正規化,儘管它稱呼起來都是說滿足了第三正規化。
現實中的業務往往有著自身的規律與約束,乙個庫模型,在滿足第三正規化時也滿足了更高的正規化,有時是乙個很自然的事。相反,滿足了第三正規化但違反了更高的正規化,這時候就要小心對待,這裡很容易發生設計錯誤。
在實際的操作中,高正規化往往代表著更多的連線,有時為了更好的響應速度、更便捷的某些操作,設計時會特意降低正規化或違反正規化。這種設計理念與本文的重點----「滿足了第三正規化但違反了更高的正規化,這時候很容易發生設計錯誤」要注意區分開。
在繼續下文前,先回顧下前三個正規化的概念:
第一正規化,表的列(關係的屬性)是不可再分的,不能是復合的,每一列各自表示乙個屬性。這個也是關聯式資料庫最基本的要求,不滿足第一正規化也就無法說什麼關係的資料庫。
第二正規化,在第一正規化的基礎上,表中的每一行可以被唯一地區分。
第三正規化,滿足第二正規化,並在候選鍵上不存在傳遞依賴。
「乙個設計滿足了第三正規化,但可能違反了更高正規化」--這條警示什麼時候該響起?以下諸情況就是一些高危區:1.乙個表是否與多個表關聯,特別是參與了多個多對多關係。2表包含著復合鍵。3使用的不是自然鍵而是**鍵。
下面以一些容易出錯的關係表舉例:
1.滿足第三正規化,但不滿足第四正規化
第四正規化關注的是多值依賴。
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.第六正規化是將表的關係減少到只存在乙個非關鍵屬性,這樣會導致表數量膨脹,但可以避免空值列。第六正規化的情況很少,未在文中討論,放在這裡只是記錄一下。
第一正規化,第二正規化,第三正規化
第一正規化 存在非主屬性對碼的部分依賴關係 r a,b,c ab是碼 c是非主屬性 b c b決定c c部分依賴於b 第一正規化 定義 如果關係r 中所有屬性的值域都是單純域,那麼關係模式r是第一正規化的 那麼符合第一模式的特點就有 1 有主關鍵字 2 主鍵不能為空,3 主鍵不能重複,4 欄位不可以...
第一正規化,第二正規化,第三正規化
第一正規化 存在非主屬性對碼的部分依賴關係 r a,b,c ab是碼 c是非主屬性 b c b決定c c部分依賴於b 第一正規化 定義 如果關係r 中所有屬性的值域都是單純域,那麼關係模式r是第一正規化的 那麼符合第一模式的特點就有 1 有主關鍵字 2 主鍵不能為空,3 主鍵不能重複,4 欄位不可以...
第一正規化,第二正規化,第三正規化
第一正規化 存在非主屬性對碼的部分依賴關係 r a,b,c ab是碼 c是非主屬性 b c b決定c c部分依賴於b 第一正規化 定義 如果關係r 中所有屬性的值域都是單純域,那麼關係模式r是第一正規化的 那麼符合第一模式的特點就有 1 有主關鍵字 2 主鍵不能為空,3 主鍵不能重複,4 欄位不可以...