規範化-數據庫設計原則

關係數據庫設計的核心問題是關係模型的設計。本文將結合具體的實例,介紹數據庫設計規範化的流程。數據庫

摘要

關係型數據庫是當前普遍應用的數據庫類型,關係數據庫設計是對數據進行組織化和結構化的過程,核心問題是關係模型的設計。對於數據庫規模較小的狀況,咱們能夠比較輕鬆的處理數據庫中的表結構。然而,隨着項目規模的不斷增加,相應的數據庫也變得更加複雜,關係模型表結構更爲龐雜,這時咱們每每會發現咱們寫出來的SQL語句的是很笨拙而且效率低下的。更糟糕的是,因爲表結構定義的不合理,會致使在更新數據時形成數據的不完整。所以,就有必要學習和掌握數據庫的規範化流程,以指導咱們更好的設計數據庫的表結構,減小冗餘的數據,藉此能夠提升數據庫的存儲效率,數據完整性和可擴展性。本文將結合具體的實例,介紹數據庫規範化的流程。數據結構


序言

本文的目的就是經過詳細的實例來闡述規範化的數據庫設計原則。在DB2中,簡潔、結構明晰的表結構對數據庫的設計是至關重要的。規範化的表結構設計,在之後的數據維護中,不會發生插入(insert)、刪除(delete)和更新(update)時的異常。反之,數據庫表結構設計不合理,不只會給數據庫的使用和維護帶來各類各樣的問題,並且可能存儲了大量不須要的冗餘信息,浪費系統資源。數據庫設計

要設計規範化的數據庫,就要求咱們根據數據庫設計範式――也就是數據庫設計的規範原則來作。可是一些相關材料上提到的範式設計,每每是給出一大堆的公式,這給設計者的理解和運用形成了必定的困難。所以,本文將結合具體形象的例子,儘量通俗化地描述三個範式,以及如何在實際工程中加以優化應用。學習


規範化

在設計和操做維護數據庫時,關鍵的步驟就是要確保數據正確地分佈到數據庫的表中。 使用正確的數據結構,不只便於對數據庫進行相應的存取操做,並且能夠極大地簡化應用程序的其餘內容(查詢、窗體、報表、代碼等)。正確進行表設計的正式名稱就是"數據庫規範化"。後面咱們將經過實例來講明具體的規範化的工程。關於什麼是範式的定義,請參考附錄文章 1.優化


數據冗餘

數據應該儘量少地冗餘,這意味着重複數據應該減小到最少。好比說,一個部門僱員的電話不該該被存儲在不一樣的表中, 由於這裏的電話號碼是僱員的一個屬性。若是存在過多的冗餘數據,這就意味着要佔用了更多的物理空間,同時也對數據的維護和一致性檢查帶來了問題,當這個員工的電話號碼變化時,冗餘數據會致使對多個表的更新動做,若是有一個表不幸被忽略了,那麼就可能致使數據的不一致性。spa


 

規範化實例

爲了說明方便,咱們在本文中將使用一個SAMPLE數據表,來一步一步分析規範化的過程。設計

首先,咱們先來生成一個的最初始的表。code

CREATE TABLE "SAMPLE" (
          "PRJNUM" INTEGER NOT NULL, 
          "PRJNAME" VARCHAR(200), 
          "EMYNUM" INTEGER NOT NULL,
          "EMYNAME" VARCHAR(200), 
          "SALCATEGORY" CHAR(1), 
          "SALPACKAGE" INTEGER)   
         IN "USERSPACE1";

ALTER TABLE "SAMPLE" 
    ADD PRIMARY KEY
        ("PRJNUM", "EMYNUM");

Insert into SAMPLE(PRJNUM, PRJNAME, EMYNUM, EMYNAME, SALCATEGORY, SALPACKAGE)
values(100001, 'TPMS', 200001, 'Johnson', 'A', 2000), (100001, 'TPMS', 200002,
'Christine', 'B', 3000), (100001, 'TPMS', 200003, 'Kevin', 'C', 4000), (100002,
'TCT', 200001, 'Johnson', 'A', 2000), (100002, 'TCT', 200004, 'Apple', 'B',
3000);
表1-1

表1-1

考察表1-1,咱們能夠看到,這張表一共有六個字段,分析每一個字段都有重複的值出現,也就是說,存在數據冗餘問題。這將潛在地形成數據操做(好比刪除、更新等操做)時的異常狀況,所以,須要進行規範化。orm


 

第一範式

參照範式的定義,考察上表,咱們發現,這張表已經知足了第一範式的要求。htm

一、由於這張表中字段都是單一屬性的,不可再分;

二、並且每一行的記錄都是沒有重複的;

三、存在主屬性,並且全部的屬性都是依賴於主屬性;

四、全部的主屬性都已經定義

事實上在當前全部的關係數據庫管理系統(DBMS)中,都已經在建表的時候強制知足第一範式。所以,這張SAMPLE表已是一張知足第一範式要求的表。考察表1-1,咱們首先要找出主鍵。能夠看到,屬性對<Project Number, Employee Number>是主鍵,其餘全部的屬性都依賴於該主鍵。


 

從一範式轉化到二範式

根據第二範式的定義,轉化爲二範式就是消除部分依賴。

考察表1-1,咱們能夠發現,非主屬性<Project Name>部分依賴於主鍵中的<Project Number>; 非主屬性<Employee Name>,<Salary Category>和<Salary package>都部分依賴於主鍵中的<Employee Number>;

表1-1的形式,存在着如下潛在問題:

1. 數據冗餘:每個字段都有值重複;

2. 更新異常:好比<Project Name>字段的值,好比對值"TPMS"了修改,那麼就要一次更新該字段的多個值;

3. 插入異常:若是新建了一個Project,名字爲TPT, 可是尚未Employee加入,那麼<Employee Number>將會空缺,而該字段是主鍵的一部分,所以將沒法插入記錄;

Insert into SAMPLE(PRJNUM, PRJNAME, EMYNUM, EMYNAME, SALCATEGORY, SALPACKAGE) values(100003, 'TPT', NULL, NULL, NULL, NULL)

4. 刪除異常:若是一個員工 200003, Kevin 離職了,要將該員工的記錄從表中刪除,而此時相關的Salary信息 C 也將丟失, 由於再沒有別的行紀錄下 Salary C的信息。

Delete from sample where EMYNUM = 200003
Select distinct SALCATEGORY, SALPACKAGE from SAMPLE

所以,咱們須要將存在部分依賴關係的主屬性和非主屬性從知足第一範式的表中分離出來,造成一張新的表,而新表和舊錶之間是一對多的關係。由此,咱們獲得:

CREATE TABLE "PROJECT" (
          "PRJNUM" INTEGER NOT NULL, 
          "PRJNAME" VARCHAR(200))
         IN "USERSPACE1";

ALTER TABLE "PROJECT" 
    ADD PRIMARY KEY
        ("PRJNUM");

Insert into PROJECT(PRJNUM, PRJNAME) values(100001, 'TPMS'), (100002, 'TCT');
表1-2

表1-2

表 1-3
CREATE TABLE "EMPLOYEE" (
          "EMYNUM" INTEGER NOT NULL, 
          "EMYNAME" VARCHAR(200), 
"SALCATEGORY" CHAR(1), 
"SALPACKAGE" INTEGER)
         IN "USERSPACE1";

ALTER TABLE "EMPLOYEE" 
    ADD PRIMARY KEY
        ("EMYNUM");

Insert into EMPLOYEE(EMYNUM, EMYNAME, SALCATEGORY, SALPACKAGE) values(200001,
'Johnson', 'A', 2000), (200002, 'Christine', 'B', 3000), (200003, 'Kevin', 'C',
4000), (200004, 'Apple', 'B', 3000);

Employee Number    Employee Name    Salary Category    Salary Package
200001    Johnson    A    2000
200002    Christine    B    3000
200003    Kevin    C    4000
200004    Apple    B    3000
CREATE TABLE "PRJ_EMY" (
          "PRJNUM" INTEGER NOT NULL, 
          "EMYNUM" INTEGER NOT NULL)
         IN "USERSPACE1";

ALTER TABLE "PRJ_EMY" 
    ADD PRIMARY KEY
        ("PRJNUM", "EMYNUM");

Insert into PRJ_EMY(PRJNUM, EMYNUM) values(100001, 200001), (100001, 200002),
(100001, 200003), (100002, 200001), (100002, 200004);

同時,咱們把表1-1的主鍵,也就是表1-2和表1-3的各自的主鍵提取出來,單獨造成一張表,來代表表1-2和表1-3之間的關聯關係:

表 1-4

表 1-4

這時候咱們仔細觀察一下表1-2, 1-3, 1-4, 咱們發現插入異常已經不存在了,當咱們引入一個新的項目 TPT 的時候,咱們只須要向表1-2 中插入一條數據就能夠了, 當有新人加入項目 TPT 的時候,咱們須要向表1-3, 1-4 中各插入一條數據就能夠了。雖然咱們解決了一個大問題,可是仔細觀察咱們仍是發現有問題存在。


 

從二範式轉化到三範式

考察表前面生成的三張表,咱們發現,表1-3存在傳遞依賴關係,即:關鍵字段< Employee Number > --> 非關鍵字段< Salary Category > -->非關鍵字段< Salary Package >。而這是不知足三範式的規則的,存在如下的不足:

一、 數據冗餘:<Salary Category>和<Salary Package>的值有重複;

二、 更新異常:有重複的冗餘信息,修改時須要同時修改多條記錄,不然會出現數據不一致的狀況;

三、 刪除異常:一樣的,若是員工 200003 Kevin 離開了公司,會直接致使 Salary C 的信息的丟失。

Delete from EMPLOYEE where EMYNUM = 200003
Select distinct SALCATEGORY, SALPACKAGE from EMPLOYEE

所以,咱們須要繼續進行規範化的過程,把表1-3拆開,咱們獲得:

表 1-5

表 1-5

表 1-6

表 1-6

這時候若是 200003 Kevin 離開公司,咱們只須要從表 1-5 中刪除他就能夠了, 存在於表1-6中的Salary C信息並不會丟失。可是咱們要注意到除了表 1-5 中存在 Kevin 的信息以外, 表1-4中也存在 Kevin 的信息, 這很容易理解, 由於 Kevin 參與了項目 100001, TPMS, 因此固然也要從中刪除。

至此,咱們將表1-1通過規範化步驟,獲得四張表,知足了三範式的約束要求,數據冗餘、更新異常、插入異常和刪除異常。

在三範式之上,還存在着更爲嚴格約束的BC範式和四範式,可是這兩種形式在商業應用中不多用到,在絕大多數狀況下,三範式已經知足了數據庫表規範化的要求,有效地解決了數據冗餘和維護操做的異常問題。


 

結束語

在本文描述的過程當中,咱們經過結合實例的方法,通俗地演繹了數據表規範化的過程,並展現了在此過程當中數據冗餘、數據庫操做異常等問題是如何獲得解決的。

在具體的工程應用中,運用數據庫規範化的方法來設計數據庫表,將是具備現實意義的。

參考資料


 轉自:http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0605jiangt/

相關文章
相關標籤/搜索