1. 程式人生 > >資料庫系統實現學習筆記三(更新異常與規範化設計)--by穆晨

資料庫系統實現學習筆記三(更新異常與規範化設計)--by穆晨

前言

        在前兩篇中,主要講了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就是一個平凡函式依賴。

   即一個TravelCampaignName由TravelCampaignID唯一確定,所以稱Travel函式決定TravelCampaignName,或稱Trave函式依賴於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,它是目前最受資料分析師,資料探勘工程師們歡迎的語言。

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