NO IMAGE

一、基本介紹

設計關聯式資料庫時,遵從不同的規範要求,設計出合理的關係型資料庫,這些不同的規範要求被稱為不同的正規化,各種正規化呈遞次規範,越高的正規化資料庫冗餘越小。

目前關聯式資料庫有六種正規化:第一正規化(1NF)、第二正規化(2NF)、第三正規化(3NF)、巴斯-科德正規化(BCNF)、第四正規化(4NF)和第五正規化(5NF,又稱完美正規化)。滿足最低要求的正規化是第一正規化(1NF)。在第一正規化的基礎上進一步滿足更多規範要求的稱為第二正規化(2NF),其餘正規化以次類推。一般說來,資料庫只需滿足第三正規化(3NF)就行了。

正規化的包含關係。一個資料庫設計如果符合第二正規化,一定也符合第一正規化。如果符合第三正規化,一定也符合第二正規化…

資料庫基本概念
要理解正規化,首先必須對知道什麼是關聯式資料庫,簡單的說:關聯式資料庫就是用二維表來儲存資料。表和表之間可以……(省略10W字),如果對資料庫很熟悉,可以不用理會下面的概念。

  1. 實體:現實世界中客觀存在並可以被區別的事物。比如“一個學生”、“一本書”、“一門課”等等。值得強調的是這裡所說的“事物”不僅僅是看得見摸得著的“東西”,它也可以是虛擬的,不如說“老師與學校的關係”。
  2. 屬性:教科書上解釋為:“實體所具有的某一特性”,由此可見,屬性一開始是個邏輯概念,比如說,“性別”是“人”的一個屬性。在關聯式資料庫中,屬性又是個物理概念,屬性可以看作是“表的一列”。
  3. 元組:表中的一行就是一個元組。
  4. 分量:元組的某個屬性值。在一個關聯式資料庫中,它是一個操作原子,即關聯式資料庫在做任何操作的時候,屬性是“不可分的”。否則就不是關聯式資料庫了。
  5. 碼:表中可以唯一確定一個元組的某個屬性(或者屬性組),如果這樣的碼有不止一個,那麼大家都叫 候選碼,我們從候選碼中挑一個出來做老大,它就叫主碼。
  6. 全碼:如果一個碼包含了所有的屬性,這個碼就是全碼。
  7. 主屬性:一個屬性只要在任何一個候選碼中出現過,這個屬性就是主屬性
  8. 外碼:一個屬性(或屬性組),它不是碼,但是它別的表的碼,它就是外碼。
  9. 候選碼: 若關係中的某一屬性或屬性組的值能唯一的標識一個元組,而其任何真子集都不能再標識,則稱該屬性組為(超級碼)候選碼。

二、6種正規化
前面說到,正規化越高,資料的冗餘度越小。其實沒有冗餘的資料庫設計是可以做到的。但是,沒有冗餘的資料庫未必是最好的資料庫,有時為了提高執行效率,就必須降低正規化標準,適當保留冗餘資料。具體做法是:在概念資料模型設計時遵守第三正規化,降低正規化標準的工作放到物理資料模型設計時考慮。降低正規化就是增加欄位,允許冗餘。(最典型的就是在一些資料表中不僅存作為外來鍵的user_id,同樣存user_name,這樣雖然違反資料庫正規化增加了user_name欄位,但是卻提高了效率,減少了獲取user_id後再去user表中獲取user name的操作)
所以實際中,我們只需要考慮資料庫滿足第三正規化就可以了,下面以最通俗的方式來解釋資料庫的正規化。

第一正規化(1NF):屬性不可分

    (1NF是對屬性的原子性約束,要求屬性具有原子性,不可再分解)
name                    tel                 age
手機           座機
Josh        13612345678    021-9876543       22
Wang        39887766555    010-1234567       21

很明顯,tel這個屬性還可以進行分解,分解成手機和座機這兩個屬性,不滿足第一正規化的資料庫,不是關聯式資料庫!所以,我們在任何關聯式資料庫管理系統中,做不出這樣的“表”來。

第二正規化(2NF):符合1NF,並且非主屬性完全依賴於碼。
(2NF是對記錄的惟一性約束,要求記錄有惟一標識,即實體的惟一性,更通俗說有主鍵ID)都不能理解,只能看看如下科學的解釋了:
一個候選碼中的主屬性也可能是好幾個。如果一個主屬性,它不能單獨做為一個候選碼,那麼它也不能確定任何一個非主屬性。給一個反例:我們考慮一個小學的教務 管理系統,學生上課指定一個老師,一本教材,一個教室,一個時間,大家都上課去吧,沒有問題。那麼資料庫怎麼設計?(學生上課表)

學生       課程             老師    老師職稱         教材   教室      上課時間
小明       一年級語文(上)  大寶     副教授    《小學語文1》 101   14:30
一個學生上一門課,一定在特定某個教室。所以有(學生,課程)->教室
一個學生上一門課,一定是特定某個老師教。所以有(學生,課程)->老師
一個學生上一門課,他老師的職稱可以確定。所以有(學生,課程)->老師職稱
一個學生上一門課,一定是特定某個教材。所以有(學生,課程)->教材
一個學生上一門課,一定在特定時間。所以有(學生,課程)->上課時間

因此(學生,課程)是一個碼。

然而,一個課程,一定指定了某個教材,一年級語文肯定用的是《小學語文1》,那麼就有課程->教材。(學生,課程)是個碼,課程卻決定了教材,這就叫做不完全依賴,或者說部分依賴。出現這樣的情況,就不滿足第二正規化!有什麼不好嗎?你可以想想:

    1、校長要新增加一門課程叫“微積分”,教材是《大學數學》,怎麼辦?學生還沒選課,而學生又是主屬性,主屬性不能空,課程怎麼記錄呢,教材記到哪呢? ……鬱悶了吧?(插入異常)
2、下學期沒學生學一年級語文(上)了,學一年級語文(下)去了,那麼表中將不存在一年級語文(上),也就沒了《小學語文1》。這時候,校長問:一年級語文(上)用的什麼教材啊?……鬱悶了吧?(刪除異常)
3、校長說:一年級語文(上)換教材,換成《大學語文》。有10000個學生選了這麼課,改動好大啊!改累死了……鬱悶了吧?(修改異常)

那應該怎麼解決呢?投影分解,將一個表分解成兩個或若干個表

學生 課程 老師 老師職稱 教室 上課時間
小明 一年級語文(上) 大寶 副教授 101 14:30

學生上課表
課程 教材
一年級語文(上) 《小學語文1》

第三正規化(3NF):符合2NF,並且,消除傳遞依賴。
(3NF是對欄位冗餘性的約束,即任何欄位不能由其他欄位派生出來,它要求欄位沒有冗餘)
正如前面所說:沒有資料冗餘的資料庫並不一定是最好的資料庫,所以有沒有冗餘的設計,要綜合來考慮。

上面的“學生上課表”符合2NF,可以這樣驗證:兩個主屬性單獨使用,不用確定其它四個非主屬性的任何一個。但是它有傳遞依賴!在“老師”和“老師職稱”這裡,一個老師一定能確定一個老師職稱。
如果不消除這種傳遞依賴,有可能會出現:
1、老師升級了,變教授了,要改資料庫,表中有N條,改了N次……(修改異常)
2、沒人選這個老師的課了,老師的職稱也沒了記錄……(刪除異常)
3、新來一個老師,還沒分配教什麼課,他的職稱記到哪?……(插入異常)
那應該怎麼解決呢?和上面一樣,投影分解:
學生 課程 老師 教室 上課時間
小明 一年級語文(上) 大寶 101 14:30

老師 老師職稱
大寶 副教授

BCNF:符合3NF,並且,主屬性不依賴於主屬性。

若關係模式屬於第二正規化,且每個屬性都不傳遞依賴於鍵碼,則R屬於BC正規化。

通常
BC正規化的條件有多種等價的表述:每個非平凡依賴的左邊必須包含鍵碼;每個決定因素必須包含鍵碼。

BC正規化既檢查非主屬性,又檢查主屬性。當只檢查非主屬性時,就成了第三正規化。滿足BC正規化的關係都必然滿足第三正規化。
還可以這麼說:若一個關係達到了第三正規化,並且它只有一個候選碼,或者它的每個候選碼都是單屬性,則該關係自然達到BC正規化。

一般,一個資料庫設計符合3NF或BCNF就可以了。

第四正規化:要求把同一表內的多對多關係刪除。
第五正規化:從最終結構重新建立原始結構。