更新異常與規範化設計

前言

        在前兩篇中,主要講了ER建模和關係建模。在具體分析如何用數據庫管理軟件RDBMS(Relational Database Management System)實現這些關係前,我想有必要思考下面這個問題:

        爲什麼要這麼麻煩?爲什麼又是ER建模又是關係建模的?

        本篇的出發點就是回答這個問題。然而某種程度上,也是回答另一個本質性的問題:爲什麼要有數據庫?

 

更新異常

        數據庫的四大操作:增,刪,改,查中,除了查,其他三個都可歸爲更新操作。而總的來說,ER建模和關係建模的目的,就是爲了避免因大量冗餘數據導致的數據庫更新異常。

        接下來本文將使用一張旅遊公司的數據表,來具體分析沒有ER建模和關係建模將導致的問題。

        該數據表將由以下這些列組成:

       

        下面是該表內的一部分數據:

       

        (字看不清的話請將圖片下載到本地觀看)

        看到這張表的第一眼,就能發現有很多冗餘數據存在,比如紅框中的部分:

       

        爲什麼信息冗餘會導致更新異常呢?下面將對三種更新操作:插入,刪除,修改可能出現的異常分別進行分析。

        1. 插入異常(insertion anomaly)

        這種異常是指當用戶想要插入某一真實世界的實體數據時,還必須輸入另一個真實世界中實體的數據。

        舉例來說,公司業務發展,新建了一個“家庭主婦團”的模式。但我要想往表裏錄入一個新的模式,還必須綁定地錄入一個新的活動。

        2. 刪除異常(deletion anomaly)

        這種異常是指當用戶要刪除某一真實世界的實體數據時,還必須刪除另一個真實世界中實體的數據。

        舉例來說,假如刪除下圖紅框中的記錄:

       

        (字看不清的話請將圖片下載到本地觀看)

        就會導致把“老年人團”這種模式的相關數據也給清除掉了。

        3. 修改異常(modification anomaly)

        這種異常是指當用戶要修改某個值的時候,同樣的修改操作需要重複多次。

        舉例來說,假如公司爲了吸引客戶,決定多送一天,因而需要將”雲南七日遊“的持續時間改爲8天。這時需要改動的地方就有三處了,如下圖紅框中所示:

       

 

函數依賴

        上述的這些更新異常,都可通過規範化設計的方式避免。在詳細介紹規範化設計之前,首先來討論一個重要的概念:函數依賴(functional dependency)。

        函數依賴,是指關係中每行記錄的某一列(或幾列)的值唯一決定該條記錄另一列的值。總的來說,有以下幾種函數依賴:

        1. 平凡函數依賴(trivial functional dependency)

        是指一個或多個屬性確定它自己,或者它的子集。如本文樣例數據集中TravelCampaignID,TravelCampaignName -> TravelCampaignID就是一個平凡函數依賴。

        注:這種依賴在規範化中不會被用到。

        2. 增廣函數依賴(augmented functional dependency)

        是指某個依賴式爲真,則依賴式左側,或者兩側同時增加某語句形成的一種依賴關係。如本文樣例數據集中TravelCampaignID,ModleID -> TravelCampaignName。因爲只需要TravelCampaignID就能夠確定TravelCampaignName了。

        注:這種依賴在規範化中不會被用到。

        3. 等價函數依賴(equivalent functional dependency)

        這種依賴關係是一對對的。比如若A->B和B->A都爲真,那麼A能推出來的,B同樣也能推出來,因此A->B和B->A就被稱作等價函數依賴。如本文樣例數據集中TravelCampaignID-> TravelCampaignName和TravelCampaignName-> TravelCampaignID。

        注:這種依賴只需保留一組依賴關係即可,但它不屬於規範化的範疇。

        4. 部分函數依賴(partial functional dependency)

        是指關係的一列函數依賴於組合主碼的一部分。顯然這種依賴只有組合主碼才存在。如本文樣例數據中ModelID->ModelName,因爲記錄的複合主碼(TravelCampaignID, ModelID)能確定記錄的任何一列,ModelID只是該複合主碼的一部分。

        注:這種依賴關係屬於規範化範疇。

        5. 完全函數依賴(full key functional dependency)

        是指複合主碼函數確定關係中的其他列,並且複合主碼的任意部分不能單獨確定其他列。這個概念和上面的部分函數依賴顯然是對立的。

        注:這種依賴關係屬於規範化範疇。

        6. 傳遞函數依賴(transitive functional dependency)

        是指非碼列函數確定關係中的其他非碼列。如本文樣例數據中CampaignManangerID->CampaignManangerName顯然就是一個傳遞函數依賴。

        這六種函數依賴中只有後面三種和規範化設計有關。前面三種則因爲對改進冗餘信息並沒有幫助,不納入規範化過程中。

 

規範化

        規範化設計能夠有效的避免數據冗餘導致的更新異常,它基於範式思想。一個關係是否滿足某種範式通常要看它是否不包含某個函數依賴。

        下面首先來看看這幾個範式的定義:

        1. 第一範式(1NF)

        一個表如果每一行都是唯一,並且任何行都沒有包含多個值的列,則它滿足1NF。但對於關係表來說,真正的規範化過程從第二範式開始,因爲關係表本身已經滿足1NF了。

        2. 第二範式(2NF)

        一個表如果滿足1NF,並且不包含部分函數依賴,則這個表滿足2NF。

        3. 第三範式(3NF)

        一個表如果滿足2NF,並且不包含傳遞函數依賴,則這個表滿足3NF。

        至於3NF以上的範式,則基於其他函數依賴,對於減少數據冗餘消除異常沒有多大幫助。這裏就不再介紹了。

        對樣例數據進行第三範式規範化後,結果如下(紅字列對應主碼):

        旅行活動表:

        

        業務經理表:

       

        遊玩模式表:

       

        旅行活動 - 遊玩模式聯繫表:

       

        現在請讀者自行思考一下,更新異常解決了嗎?答案是肯定的。但是也不能說100%的冗餘信息都去除了,比如說外碼的映射關係就重複了一次。

        那麼如果要對外碼進行變更,有什麼辦法保證不異常呢?這部分內容將在第五篇講解。

 

規範化的例外情況

        並不是說所有的關係都必須滿足3NF,沒有那麼絕對。有些時候可以考慮降到2NF。

        比如說下面這個是某公司銷售經理信息表:

       

        這張表並不滿足3NF,因爲郵編和城市之間存在了部分函數依賴,從而有信息冗餘(見上圖紅框部分)。但由於該公司同一地區最多隻有兩名銷售經理,因此冗餘情況很少,規範化到3NF讓表設計顯得過於複雜化了。因此這種情況可以考慮不升級到3NF,讓上層實現去解決冗餘問題。

 

ER建模,關係建模與規範化設計

        看到這裏,它們之間的關係也就呼之欲出了。這些建模工作的作用,就是能夠讓設計的關係更容易滿足規範化設計中的(第三)範式要求,從而減少數據冗餘,消除更新異常。

        在實際開發中,絕大部分情況還是按着ER建模->關係建模->物理模型建模來走。這樣設計出來的表絕大部分滿足第三範式,只有小部分地方需要調整一下,根據實際情況決定是選用3NF還是2NF,其中前者佔大多數情況。

        不按這個套路來,後果就是前文提到的那一堆更新異常。

 

小結

        看完本文的分析,讀者應該明白了前兩篇所做的工作:ER建模和關係建模的根本意義所在,也應該體會到了關係數據庫理論的價值。

        接下來的一篇,將講解如何具體在數據庫管理軟件RDBMS裏創建這些表,以及如何對這些表進行增,刪,改,查等操作。這些工作將使用到大名鼎鼎的SQL,它是目前最受數據分析師,數據挖掘工程師們歡迎的語言。

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