為企業(yè)設(shè)計(jì)數(shù)據(jù)庫時(shí),主要目標(biāo)是正確的表示數(shù)據(jù)、數(shù)據(jù)之間的聯(lián)系以及與企業(yè)業(yè)務(wù)相關(guān)的數(shù)據(jù)約束。為了實(shí)現(xiàn)這個(gè)目標(biāo),我們可以使用一種或多種數(shù)據(jù)庫設(shè)計(jì)技術(shù)。前面講了實(shí)體 - 聯(lián)系(ER)建模。下面將講述另一種數(shù)據(jù)庫設(shè)計(jì)技術(shù)——規(guī)范化。
規(guī)范化 是一種數(shù)據(jù)庫設(shè)計(jì)技術(shù),從分析屬性之間的聯(lián)系(即函數(shù)依賴)入手。屬性刻畫了企業(yè)重要數(shù)據(jù)的特性或者這些數(shù)據(jù)之間聯(lián)系的特性。規(guī)范化使用一系列測(cè)試(描述為范式)幫助我們確定這些屬性的最佳組合,最終生成可支持企業(yè)數(shù)據(jù)需求的一組適當(dāng)關(guān)系。
本篇主要目標(biāo)是介紹函數(shù)依賴的概念,并且討論如何將關(guān)系規(guī)范化到第三范式。下一篇還將給出函數(shù)依賴的形式化描述以及比 3NF 更高的范式。
1. 規(guī)范化的目的
規(guī)范化(normalization):生成一組既具有所期望的特性又能滿足企業(yè)數(shù)據(jù)需求的關(guān)系的技術(shù)。
進(jìn)行規(guī)范化的目的是確定一組合適的關(guān)系以支持企業(yè)的數(shù)據(jù)需求。所謂合適的關(guān)系,應(yīng)具有如下性質(zhì):
- 屬性的個(gè)數(shù)最少,且這些屬性是支持企業(yè)的數(shù)據(jù)需求所必需的。
- 具有緊密邏輯聯(lián)系(描述為 函數(shù)依賴)的諸屬性均在同一關(guān)系中。
- 最少 的冗余,即每個(gè)屬性僅出現(xiàn)一次,作為外部關(guān)鍵字的屬性除外。連接相關(guān)關(guān)系必須用到外部關(guān)鍵字。
數(shù)據(jù)庫擁有一組合適的關(guān)系的好處是:數(shù)據(jù)庫易于用戶訪問,數(shù)據(jù)易于維護(hù),在計(jì)算機(jī)上占有較小的存儲(chǔ)空間。而使用未能被適當(dāng)規(guī)范化的關(guān)系帶來的問題詳見第 3 小節(jié)。
2. 規(guī)范化對(duì)數(shù)據(jù)庫設(shè)計(jì)的支持
規(guī)范化是一種能夠應(yīng)用于數(shù)據(jù)庫設(shè)計(jì)任何階段的形式化技術(shù)。這里著重強(qiáng)調(diào)規(guī)范化的兩種使用方法。方法 1 將規(guī)范化視為一種自下而上的獨(dú)立的數(shù)據(jù)庫設(shè)計(jì)技術(shù)。方法 2 則將規(guī)范化作為一種確認(rèn)技術(shù)使用:用規(guī)范化技術(shù)檢驗(yàn)關(guān)系的結(jié)構(gòu),而這些關(guān)系的建立可能采用自上而下的方法,比如 ER 建模。不管使用哪一種方法,目標(biāo)都是一致的,即建立一組設(shè)計(jì)良好(well-designed)的關(guān)系以滿足企業(yè)的數(shù)據(jù)需求。

上圖給出了一些能夠用來進(jìn)行數(shù)據(jù)庫設(shè)計(jì)的數(shù)據(jù)源示例。盡管用戶的需求規(guī)格說明書是首選的數(shù)據(jù)源,但是僅基于直接從其他數(shù)據(jù)源獲得的信息進(jìn)行數(shù)據(jù)庫設(shè)計(jì)也是可能的,這些數(shù)據(jù)源包括表單和報(bào)表。上圖還說明對(duì)同一個(gè)數(shù)據(jù)源兩種方法均適用。然而盡管理論上如此,實(shí)際操作時(shí)究竟采用哪一種方法還要取決于數(shù)據(jù)源反映出的數(shù)據(jù)庫的大小、范圍以及復(fù)雜度,同時(shí)還取決于數(shù)據(jù)庫設(shè)計(jì)者的偏好及其專長(zhǎng)。是否將規(guī)范化作為一種自上而下的獨(dú)立的數(shù)據(jù)庫設(shè)計(jì)技術(shù)(即方法 1)使用,常常受限于數(shù)據(jù)庫設(shè)計(jì)者對(duì)設(shè)計(jì)細(xì)節(jié)的掌握程度。然而,當(dāng)我們將規(guī)范化作為一種確認(rèn)技術(shù)(即方法 2)使用時(shí),就沒有了這種限制。因?yàn)樵谶@種使用方法中,數(shù)據(jù)庫設(shè)計(jì)者在任何時(shí)刻都能專注于數(shù)據(jù)庫的一部分,例如一個(gè)單一的關(guān)系,因此,不管數(shù)據(jù)庫的大小或者復(fù)雜度如何,規(guī)范化都能發(fā)揮效能。
3. 數(shù)據(jù)冗余與更新異常
如上所述,關(guān)系數(shù)據(jù)庫設(shè)計(jì)的一個(gè)主要目標(biāo)就是將屬性組合成關(guān)系時(shí)力求最少的數(shù)據(jù)冗余。如果能夠達(dá)到這個(gè)目標(biāo),就可能為數(shù)據(jù)庫帶來以下好處:
能用最少的操作完成對(duì)數(shù)據(jù)庫中存儲(chǔ)數(shù)據(jù)的更新,由此可以降低數(shù)據(jù)庫中出現(xiàn)數(shù)據(jù)不一致的概率。
減少存儲(chǔ)基本關(guān)系所需的文件存儲(chǔ)空間,因而將成本降低至最低。
當(dāng)然,關(guān)系數(shù)據(jù)庫(的運(yùn)行)也依賴于一定的數(shù)據(jù)冗余的存在。這種冗余一般是以主關(guān)鍵字(或者候選關(guān)鍵字)的多個(gè)副本的形式出現(xiàn),這些副本在與之相關(guān)聯(lián)的關(guān)系(即主關(guān)鍵字或候選關(guān)鍵字所述的關(guān)系)中,做為外部關(guān)鍵字出現(xiàn),用以表示數(shù)據(jù)之間的聯(lián)系。
舉例說明:
關(guān)系 StaffBranch 是關(guān)系 Staff 和 關(guān)系 Branch 的另一種表達(dá)方式,這些關(guān)系的結(jié)構(gòu)如下所示:
Staff (staffNo, sName, position, salary, branchNo)
Branch (branchNo, bAddress)
StaffBranch (staffNo, sName, position, salary, branchNo, bAddress)
注意,每個(gè)關(guān)系的主關(guān)鍵字都有下劃線。
在關(guān)系 StaffBranch 中存在冗余數(shù)據(jù):同一個(gè)分公司的信息在每一個(gè)屬于該分公司的員工信息里反復(fù)出現(xiàn)。相反,在關(guān)系 Branch 中,每個(gè)分公司的信息只出現(xiàn)了一次,而且在關(guān)系 Staff 中只有分公司的編號(hào)(branchNo)這一屬性的值重復(fù)出現(xiàn),這是為了能夠表示出每一個(gè)員工都?xì)w屬于哪一個(gè)分公司。存在冗余數(shù)據(jù)的關(guān)系可能存在一些問題——更新異常,更新異常又可分為插入異常、刪除異常和修改異常。關(guān)系 Staff 關(guān)系 Branch 和關(guān)系 StaffBranch表如下所示。
Staff:
| staffNo | sName | position | salary | branchNo |
|---|---|---|---|---|
| SL21 | John White | Manager | 30000 | B005 |
| SG37 | Ann Beech | Assistant | 12000 | B003 |
| SG14 | David Ford | Supervisor | 18000 | B003 |
| SA9 | Mary Howe | Assistant | 9000 | B007 |
| SG5 | Susan Brand | Manager | 24000 | B003 |
| SL41 | Julie Lee | Assistant | 9000 | B005 |
Branch:
| branchNo | bAddress |
|---|---|
| B003 | 163 Main St, Glasgow |
| B007 | 16 Argyll St, Aberdeen |
| B005 | 22 Deer Rd, London |
StaffBranch:
| staffNo | sName | position | salary | branchNo | bAddress |
|---|---|---|---|---|---|
| SL21 | John White | Manager | 30000 | B005 | 22 Deer Rd, London |
| SG37 | Ann Beech | Assistant | 12000 | B003 | 163 Main St, Glasgow |
| SG14 | David Ford | Supervisor | 18000 | B003 | 163 Main St, Glasgow |
| SA9 | Mary Howe | Assistant | 9000 | B007 | 16 Argyll St, Aberdeen |
| SG5 | Susan Brand | Manager | 24000 | B003 | 163 Main St, Glasgow |
| SL41 | Julie Lee | Assistant | 9000 | B005 | 22 Deer Rd, London |
3.1 插入異常
插入異常主要有兩類,我們用上表中的關(guān)系 StaffBranch 來解釋這兩類異常。
在關(guān)系 StaffBranch 中插入一位新員工的信息時(shí),這些信息中必須包括該員工將被分配到分公司的信息。比如,在插入某一被分配到編號(hào)為 B007 的分公司工作的員工信息時(shí),我們必須正確輸入分公司 B007 的所有信息,由此確保這些數(shù)據(jù)與關(guān)系 StaffBranch 已有的關(guān)于分公司 B007 的元組中的信息一致。而 Staff 和 Branch 關(guān)系則不存在這種潛在的不一致性,因?yàn)樵陉P(guān)系 Staff 中,秩序?yàn)槊總€(gè)員工錄入相應(yīng)的分公司編號(hào)就可以了,而在關(guān)系 Branch 中,編號(hào)為 B007 的分公司的信息是作為一個(gè)單獨(dú)的元組存儲(chǔ)在數(shù)據(jù)庫中的。
在向關(guān)系 StaffBranch 中插入一個(gè)新的分公司的信息時(shí),由于該分公司目前可能還沒有給員工,因此有必要在錄入與員工相關(guān)的信息時(shí)將其設(shè)為 NULL,如將 staffNo 賦值為 NULL。但是 staffNo 是關(guān)系 StaffBranch 的主關(guān)鍵字,若試圖為 staffNo 錄入 NULL 值,則會(huì)違反實(shí)體完整性約束,這樣做是不允許的,我們也因此無法向關(guān)系 StaffBranch 中插入一個(gè) staffNo 為 NULL的一個(gè)新的分公司的元組。Staff 和 Branch 的關(guān)系設(shè)計(jì)則避免了這類問題的出現(xiàn),因?yàn)榉止镜男畔⒃陉P(guān)系 Branch 中單獨(dú)錄入,與員工信息分離,而員工被分配到哪個(gè)分公司工作的信息則會(huì)在以后的時(shí)間再錄入關(guān)系 Staff 中。
3.2 刪除異常
從關(guān)系 StaffBranch 中刪除一個(gè)元組時(shí),若該元組表示某分公司最后一名員工,則刪除元組之后,該分公司的信息也從數(shù)據(jù)庫中丟失了。例如,如果從關(guān)系 StaffBranch 中刪除員工編號(hào)為 SA9 的元組,則編號(hào)為 B007 的分公司的信息也將從數(shù)據(jù)庫中消失。同樣的,Staff 和 Branch 的分開設(shè)計(jì)避免了這個(gè)問題。
3.3 修改異常
如果我們想要修改關(guān)系 StaffBranch 中某分公司的某個(gè)屬性值,比如修改分公司 B003 的地址,那么我們必需更新所有 B003 的員工的元組。若如此修改操作未能在關(guān)系 StaffBranch 中所有相關(guān)的元組上執(zhí)行,數(shù)據(jù)庫則會(huì)產(chǎn)生不一致:同屬分公司 B003 的員工,其元組在分公司地址這一屬性上的取值可能會(huì)有不同。
上面的示例說明了 Staff 和 Branch 的分開設(shè)計(jì)比 StaffBranch 的設(shè)計(jì)具有更令人滿意的特性。也就是說,當(dāng)關(guān)系 StaffBranch 發(fā)生更新異常時(shí),我們可以通過將其分解為 Staff 和 Branch 兩個(gè)關(guān)系來避免這些異常。當(dāng)把較大的關(guān)系分解成較小的關(guān)系時(shí),有兩個(gè)很重要的特性:
無損連接(lossless-join):該特性確保了緣關(guān)系的任意實(shí)例信息能通過較小關(guān)系的對(duì)應(yīng)實(shí)例確定出來。
依賴保持(dependency preservation):該特性確保了只需簡(jiǎn)單的在較小的關(guān)系上支持某些約束,就可以繼續(xù)支持在原關(guān)系上存在的約束。也就是說,我們不必對(duì)較小的關(guān)系執(zhí)行連接操作就可以檢驗(yàn)他們是否違反了原關(guān)系上的約束。
4. 函數(shù)依賴
與規(guī)范化相關(guān)的一個(gè)重要概念就是 函數(shù)依賴,函數(shù)依賴描述了屬性之間的聯(lián)系(Maier,1983)。
4.1 函數(shù)依賴的特征
為了討論函數(shù)依賴,假設(shè)有某一關(guān)系模式,該關(guān)系模式具有屬性(A,B,C, ... ,Z),我們用一個(gè) 全域關(guān)系(universal relation)R = (A,B,C,...,Z)來描述數(shù)據(jù)庫。該假設(shè)意味著每個(gè)數(shù)據(jù)庫中的屬性都有一個(gè)唯一的名字。
函數(shù)依賴(functional dependency):描述一個(gè)關(guān)系中屬性之間的聯(lián)系。例如,假設(shè) A 和 B 均為關(guān)系 R 的屬性,若 A 的每個(gè)值都和 B 中一個(gè)唯一的值相對(duì)應(yīng),則稱 B 函數(shù)依賴于 A,記為 A → B(A,B可能由一個(gè)或多個(gè)屬性組成)。
函數(shù)依賴是屬性在關(guān)系中的一種語義特性。該語義特性表明了屬性和屬性是如何關(guān)聯(lián)起來的,確定了屬性之間的函數(shù)依賴。當(dāng)存在某一函數(shù)依賴時(shí),這個(gè)以來就被視為屬性之間的一種 約束。
考慮某一關(guān)系,它擁有屬性 A、B,其中屬性 B 函數(shù)依賴于屬性 A。假設(shè)知道 A 的值,我們來驗(yàn)證該關(guān)系是否支持這種依賴。結(jié)果我們發(fā)現(xiàn)無論任何時(shí)候,對(duì)于所有元組,若屬性 A 的值等于給定值,則該元組的屬性 B 的值都是唯一的。因此,當(dāng)兩個(gè)元組的屬性 A 的值相同時(shí),其屬性 B 的值也是相同的。反之則不然,對(duì)于一個(gè)給定的 B 的值,可能對(duì)應(yīng)著幾個(gè)不同的 A 的值。屬性 A、B 之間這種以來可以用下圖表示。

另外一種描述屬性 A、B 之間的這種聯(lián)系的術(shù)語為 “A 函數(shù)決定 B”。也許一些讀者更喜歡使用后者,因?yàn)樗c屬性之間的函數(shù)依賴的箭頭的方向相同,顯得更自然一些。
決定方:位于函數(shù)依賴箭頭左邊的屬性或?qū)傩越M。
當(dāng)存在函數(shù)依賴時(shí),位于箭頭左邊的屬性或?qū)傩越M稱為 決定方(determinant) 。例如,上圖中,A 是 B 的決定方。
在確定一個(gè)關(guān)系中屬性間的函數(shù)依賴時(shí),必須明確它是僅當(dāng)屬性取某一特定值時(shí)成立,還是該屬性取值集中任意值時(shí)均成立,區(qū)分清楚這一點(diǎn)很重要。換句話說,函數(shù)依賴是關(guān)系模式(內(nèi)涵)的性質(zhì),而不是模式的某個(gè)實(shí)例(外延)的性質(zhì)。
另一個(gè)規(guī)范化時(shí)有用的函數(shù)依賴的性質(zhì)是:決定方應(yīng)該具有最少的屬性,這些屬性是保證右邊的屬性函數(shù)依賴于它所必不可少的。我們稱其為 完全函數(shù)依賴。
完全函數(shù)依賴(full functional dependency):假設(shè) A 和 B 是某一關(guān)系的屬性(組),若 B 函數(shù)依賴于 A,但不函數(shù)依賴于 A 的任一真子集,則稱 B 完全函數(shù)依賴于 A。
對(duì)于函數(shù)依賴 A → B,如果去掉 A 中的任一屬性都使得該依賴不再成立,那么 A → B 就是完全函數(shù)依賴。如果去掉 A 中的某些屬性,依賴仍然成立,那么函數(shù)依賴 A → B 就是 部分函數(shù)依賴。
概括而言,規(guī)范化時(shí)要用到的函數(shù)依賴具有下列性質(zhì):
- 函數(shù)依賴左邊的屬性(組)(即決定方)與右邊的屬性(組)是一對(duì)一的聯(lián)系(注意,若反過來看,也就是右邊與左邊的屬性(組)之間則既可能為一對(duì)一的聯(lián)系,也可能為一對(duì)多的聯(lián)系)。
- 恒成立。
- 決定方具有最少的、足以支持與右邊的屬性(組)之間依賴關(guān)系的屬性,即右邊的屬性(組)完全依賴于左邊的屬性(組)。
至此,我們已經(jīng)討論了在規(guī)范化時(shí)所關(guān)心的一些函數(shù)依賴,但是還有必要了解一種函數(shù)依賴,即 傳遞依賴(transitive dependency)。因?yàn)殛P(guān)系中若存在傳遞依賴,就有可能引起更新異常。本節(jié)只簡(jiǎn)單介紹傳遞依賴,目的是在需要時(shí)我們能夠識(shí)別出他們。
傳遞依賴:假設(shè) A、B、C 是某一關(guān)系的屬性,若 A → B,B → C,則稱 C 通過 B 傳遞依賴于 A(假設(shè) A 并不函數(shù)依賴于 B 或 C)。
4.2 識(shí)別函數(shù)依賴
如果我們能夠完全理解每一個(gè)屬性的意義以及這些屬性之間的聯(lián)系,那么確定屬性之間所有的函數(shù)依賴應(yīng)該非常簡(jiǎn)單。這類信息應(yīng)由企業(yè)提供,可能是通過與用戶討論形成,同時(shí)(或者)也可能是以文檔的形式出現(xiàn),比如用戶需求規(guī)格說明書。但是,如果與用戶無法溝通,并且(或者)文檔并不完備,那么數(shù)據(jù)庫設(shè)計(jì)人員就有必要基于該數(shù)據(jù)庫應(yīng)用的領(lǐng)域,利用自己的常識(shí)或經(jīng)驗(yàn)來補(bǔ)充那些缺失的信息。
4.3 利用函數(shù)依賴確定主關(guān)鍵字
確定關(guān)系函數(shù)依賴集的主要目的是確定該關(guān)系必須滿足的完整性約束集。首先要考慮辨別的一種重要的完整性約束是候選關(guān)鍵字,候選關(guān)鍵字中的一個(gè)將被選作關(guān)系的主關(guān)鍵字。
5. 規(guī)范化過程
規(guī)范化是一種基于關(guān)系的主關(guān)鍵字(或者候選關(guān)鍵字)和函數(shù)依賴對(duì)關(guān)系進(jìn)行分析的形式化技術(shù)(Codd,1972b)。規(guī)范化技術(shù)涉及一系列的規(guī)則,這些規(guī)則能夠用來對(duì)關(guān)系進(jìn)行單獨(dú)測(cè)試以保證數(shù)據(jù)庫可以被規(guī)范化到任意程度。當(dāng)某種規(guī)范化的要求未能得到滿足時(shí),就將違反需求的關(guān)系分解為多個(gè)關(guān)系,直至分解后的每一個(gè)關(guān)系都能滿足規(guī)范化的要求為止。
最早提出的三個(gè)范式為第一范式(1NF)、第二范式(2NF)和第三范式(3NF)。后來,R.Boyce 和 E.F.Codd 又提出了一種增強(qiáng)的第三范式,稱為 Boyce-Codd 范式(BCNF)(Codd,1974)。除了第一范式,所有這些范式都是基于關(guān)系的屬性之間的函數(shù)依賴的(Maier,1983)。隨后還提出了比 BCNF 更高層的范式——第四范式(4NF)和第五范式(5NF)(Fagin,1977, 1979)。但是,需要用到第四范式、第五范式的情況相當(dāng)少。本篇中將只講述前三種范式,對(duì) BCNF、4NF 和 5NF 的討論則留到下一章進(jìn)行。
規(guī)范化的過程包括一系列步驟,每一步都對(duì)應(yīng)著某種具有已知性質(zhì)的特定范式。隨著規(guī)范化的進(jìn)行,關(guān)系的個(gè)數(shù)逐漸增多,關(guān)系的形式也逐漸受限(結(jié)構(gòu)越來越好),也就越來越不容易出現(xiàn)更新異常。對(duì)于關(guān)系數(shù)據(jù)模型,應(yīng)該認(rèn)識(shí)到在建立關(guān)系時(shí)只有滿足第一范式(1NF)的要求是必須的,后面的其他范式都是可選的,這一點(diǎn)很重要。但是為了避免出現(xiàn)前面討論過的更新異常的情況,通常建議將規(guī)范化至少進(jìn)行到第三范式(3NF)。從第一范式到第五范式是是逐步遞進(jìn)的,第二范式是在滿足第一范式的基礎(chǔ)上增加條件形成的,以此類推。
下圖為規(guī)范化過程的縱覽圖,途中突出顯示了規(guī)范化過程中每一個(gè)步驟的主要操作。

這里我們將規(guī)范化視為一種自下而上的技術(shù),主要講述如何利用這種技術(shù)從案例表單中抽取屬性信息,并先將其轉(zhuǎn)化為非范式(Unnormalized Form,UNF)表格的形式,然后將其逐漸分解以滿足每一種范式的要求,分解一直進(jìn)行到原案例表中的屬性都被分解為若干滿足 3NF 要求的關(guān)系為止。盡管這里使用的例子都是從某一范式規(guī)范化到更高一級(jí)的范式,但是,對(duì)于其他的例子來說并不一定必須這么做。在解決某些特殊問題時(shí),我們可以將 1NF 的關(guān)系轉(zhuǎn)換為 2NF 的關(guān)系,或者在某些情況下,直接將其轉(zhuǎn)化為 3NF 的關(guān)系。
為了簡(jiǎn)化對(duì)規(guī)范化的講述,我們假設(shè)在所用案例中,每一個(gè)關(guān)系都有一個(gè)函數(shù)依賴集,每一個(gè)關(guān)系都已被指派了一個(gè)主關(guān)鍵字。也就是說,在規(guī)范化的過程開始之前,充分、完全地理解屬性的意義及其之間的聯(lián)系是必要的。這些信息是進(jìn)行規(guī)范化的基礎(chǔ),我們將利用這些信息來驗(yàn)證一個(gè)關(guān)系是否已經(jīng)滿足了指定范式的要求。
6. 第一范式(1NF)
非范式(UNF):包含一個(gè)或多個(gè)重復(fù)組的表。
第一范式(1NF):屬于第一范式的關(guān)系,其每一行和每一列相交的位置有且僅有一個(gè)值。
我們開始進(jìn)行規(guī)范化之前,首先要將數(shù)據(jù)從數(shù)據(jù)源(例如標(biāo)準(zhǔn)的數(shù)據(jù)輸入表單)轉(zhuǎn)換為包含行和列的表格形式。這種格式的表是非范式的,因而被視為 非規(guī)范化的表(unnormalized table)。為了將非規(guī)范化的表轉(zhuǎn)化為第一范式,我們需要確定并刪除表中的重復(fù)組。一個(gè)重復(fù)組可以是一個(gè)屬性或一組屬性,它對(duì)應(yīng)表的某個(gè)(些)關(guān)鍵屬性的一個(gè)實(shí)例可能出現(xiàn)多個(gè)值。注意,這里所說的 “關(guān)鍵屬性” 是指非規(guī)范化的表中那些可以唯一標(biāo)識(shí)每一行的屬性(組)。從非規(guī)范化的表中消除重復(fù)組的常用方法有兩種:
在含有重復(fù)數(shù)據(jù)的那些行的空白列上輸入合適的數(shù)據(jù),也就是在需要填充的位置復(fù)制非重復(fù)數(shù)據(jù)。這種方法通常被看做是對(duì)表的平板化(flattening)處理。
將重復(fù)數(shù)據(jù)單獨(dú)移到一個(gè)新的關(guān)系中,同時(shí)也將原來關(guān)系中的關(guān)鍵屬性(組)復(fù)制到這個(gè)新的關(guān)系中。有時(shí)候,非規(guī)范化的表可能包含多個(gè)重復(fù)組,或者在重復(fù)組里又有重復(fù)組。在這些情況下,重復(fù)使用這一方法直到不再存在重復(fù)組位置。若結(jié)果關(guān)系均不含重復(fù)組,則他們都是 1NF 的。
這兩種方法得到的結(jié)果關(guān)系都是 1NF 的關(guān)系,在行、列交叉處都只包含原子(或單一)值。盡管兩種方法都是正確的,然而方法 1 在對(duì)原 UNF 的表進(jìn)行平板化的過程中也引入了較多的冗余;方法 2 則創(chuàng)建了兩個(gè)或更多的關(guān)系,這些關(guān)系的冗余度都低于原 UNF 的表的冗余度。換句話說,在對(duì)原 UNF 的表的規(guī)范化過程中,方法 2 比方法 1 做的工作更多。但是,不管從哪一種方法開始,原 UNF 的表終將被規(guī)范化為一組相同的 3NF 的關(guān)系。
7. 第二范式(2NF)
第二范式基于完全函數(shù)依賴的概念,第二范式適用于具有合成關(guān)鍵字的關(guān)系,即主關(guān)鍵字有兩個(gè)或兩個(gè)以上的屬性構(gòu)成。主關(guān)鍵字僅包含一個(gè)屬性的關(guān)系已經(jīng)至少是 2NF 的。不是 2NF 的關(guān)系可能會(huì)出現(xiàn)前面討論過的更新異常。
第二范式 (2NF):滿足第一范式的要求并且每個(gè)非主關(guān)鍵字屬性都完全函數(shù)依賴與主關(guān)鍵字的關(guān)系。
將 1NF 的關(guān)系規(guī)范化為 2NF 關(guān)系需要消除部分依賴。如果存在部分依賴,就要將部分依賴的屬性從原關(guān)系移出,移到一個(gè)新的關(guān)系中去,同時(shí)將這些屬性的決定方也復(fù)制到新的關(guān)系中。
8. 第三范式(3NF)
盡管 2NF 的關(guān)系比 1NF 關(guān)系的數(shù)據(jù)冗余度低,但是仍然存在更新異常問題。此時(shí)的更新異常是由依賴傳遞引起的,我們需要消除這種依賴,繼續(xù)將關(guān)系規(guī)范化到第三范式。
第三范式(3NF):滿足第一范式和第二范式的要求并且所有非主關(guān)鍵字屬性都不傳遞依賴于主關(guān)鍵字的關(guān)系。
將 2NF 的關(guān)系規(guī)范化為 3NF 需要消除傳遞依賴。如果存在傳遞依賴,就將傳遞依賴的屬性(組)移到一個(gè)新的關(guān)系中,并將這些屬性的決定方也復(fù)制到該關(guān)系中。
9. 2NF 和 3NF 的一般化定義
在前兩節(jié)的 2NF 和 3NF 的定義中,不允許存在對(duì)主關(guān)鍵字的部分依賴和傳遞依賴,以此避免出現(xiàn)前述的更新異?,F(xiàn)象。然而,這些定義并沒有考慮關(guān)系中的其他候選關(guān)鍵字(如果存在不止一個(gè)候選關(guān)鍵字)。下面將在考慮關(guān)系的所有候選關(guān)鍵字的基礎(chǔ)上,給出 2NF 和 3NF 的更一般化定義。注意,考慮關(guān)系的候選關(guān)鍵字并不會(huì)影響 1NF 的定義,因?yàn)?1NF 與關(guān)鍵字和函數(shù)依賴無關(guān)。在更一般化的定義中,我們規(guī)定:屬于任何一個(gè)候選關(guān)鍵字的屬性都叫做主屬性(candidate-key attribute);提到部分依賴、完全依賴和傳遞依賴時(shí)不僅僅是基于主關(guān)鍵字,而是基于所有的候選關(guān)鍵字。
第二范式(2NF):滿足第一范式的要求并且每個(gè)非主屬性都完全函數(shù)依賴于任何一個(gè)候選關(guān)鍵字的關(guān)系。
第三范式(3NF):滿足第一范式和第二范式的要求并且沒有一個(gè)非主屬性傳遞依賴于任何一個(gè)候選關(guān)鍵字。
在使用 2NF 和 3NF 的一般化定義時(shí),必須注意的是所有候選關(guān)鍵字上的部分依賴和傳遞依賴,而不只是主關(guān)鍵字上的。這使得規(guī)范化過程變得更加復(fù)雜,但一般化定義能為關(guān)系增加附加約束,從而有可能發(fā)現(xiàn)關(guān)系中隱藏的、被遺漏的冗余。
在進(jìn)行規(guī)范化時(shí),是僅簡(jiǎn)單的分析主關(guān)鍵字上的依賴,還是使用一般化定義進(jìn)行規(guī)范化,這需要權(quán)衡。前者使得規(guī)范化過程簡(jiǎn)單,并且可以發(fā)現(xiàn)關(guān)系中存在的大多數(shù)問題和明顯的數(shù)據(jù)冗余;后者則有更多的機(jī)會(huì)發(fā)現(xiàn)關(guān)系中被遺漏的冗余。實(shí)際上, 常見的情形是,無論使用基于主關(guān)鍵字的定義還是使用 2NF、3NF 的一般化定義,對(duì)關(guān)系進(jìn)行分解的結(jié)果相同。