第三篇:更新異常與規范化設計


前言

        在前兩篇中,主要講了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,它是目前最受數據分析師,數據挖掘工程師們歡迎的語言。

        好吧,之一...^_^。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM