小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

規(guī)范化-數據庫設計原則

 linyu2688 2006-09-15



陳 博, 浙江大學計算機科學與技術學院研究生
蔣 韜, IBM 上海軟件開發(fā)中心工具開發(fā)組的軟件工程師

2006 年 5 月 31 日

關系數據庫設計的核心問題是關系模型的設計。本文將結合具體的實例,介紹數據庫設計規(guī)范化的流程。

摘要

關系型數據庫是當前廣泛應用的數據庫類型,關系數據庫設計是對數據進行組織化和結構化的過程,核心問題是關系模型的設計。對于數據庫規(guī)模較小的情況,我們可以比較輕松的處理數據庫中的表結構。然而,隨著項目規(guī)模的不斷增長,相應的數據庫也變得更加復雜,關系模型表結構更為龐雜,這時我們往往會發(fā)現我們寫出來的SQL語句的是很笨拙并且效率低下的。更糟糕的是,由于表結構定義的不合理,會導致在更新數據時造成數據的不完整。因此,就有必要學習和掌握數據庫的規(guī)范化流程,以指導我們更好的設計數據庫的表結構,減少冗余的數據,借此可以提高數據庫的存儲效率,數據完整性和可擴展性。本文將結合具體的實例,介紹數據庫規(guī)范化的流程。





回頁首


序言

本文的目的就是通過詳細的實例來闡述規(guī)范化的數據庫設計原則。在DB2中,簡潔、結構明晰的表結構對數據庫的設計是相當重要的。規(guī)范化的表結構設計,在以后的數據維護中,不會發(fā)生插入(insert)、刪除(delete)和更新(update)時的異常。反之,數據庫表結構設計不合理,不僅會給數據庫的使用和維護帶來各種各樣的問題,而且可能存儲了大量不需要的冗余信息,浪費系統(tǒng)資源。

要設計規(guī)范化的數據庫,就要求我們根據數據庫設計范式――也就是數據庫設計的規(guī)范原則來做。但是一些相關材料上提到的范式設計,往往是給出一大堆的公式,這給設計者的理解和運用造成了一定的困難。因此,本文將結合具體形象的例子,盡可能通俗化地描述三個范式,以及如何在實際工程中加以優(yōu)化應用。





回頁首


規(guī)范化

在設計和操作維護數據庫時,關鍵的步驟就是要確保數據正確地分布到數據庫的表中。使用正確的數據結構,不僅便于對數據庫進行相應的存取操作,而且可以極大地簡化應用程序的其他內容(查詢、窗體、報表、代碼等)。正確進行表設計的正式名稱就是"數據庫規(guī)范化"。后面我們將通過實例來說明具體的規(guī)范化的工程。關于什么是范式的定義,請參考附錄文章 1.





回頁首


數據冗余

數據應該盡可能少地冗余,這意味著重復數據應該減少到最少。比如說,一個部門雇員的電話不應該被存儲在不同的表中, 因為這里的電話號碼是雇員的一個屬性。如果存在過多的冗余數據,這就意味著要占用了更多的物理空間,同時也對數據的維護和一致性檢查帶來了問題,當這個員工的電話號碼變化時,冗余數據會導致對多個表的更新動作,如果有一個表不幸被忽略了,那么就可能導致數據的不一致性。





回頁首


規(guī)范化實例

為了說明方便,我們在本文中將使用一個SAMPLE數據表,來一步一步分析規(guī)范化的過程。

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



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,我們可以看到,這張表一共有六個字段,分析每個字段都有重復的值出現,也就是說,存在數據冗余問題。這將潛在地造成數據操作(比如刪除、更新等操作)時的異常情況,因此,需要進行規(guī)范化。





回頁首


第一范式

參照范式的定義,考察上表,我們發(fā)現,這張表已經滿足了第一范式的要求。

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

2、而且每一行的記錄都是沒有重復的;

3、存在主屬性,而且所有的屬性都是依賴于主屬性;

4、所有的主屬性都已經定義

事實上在當前所有的關系數據庫管理系統(tǒng)(DBMS)中,都已經在建表的時候強制滿足第一范式。因此,這張SAMPLE表已經是一張滿足第一范式要求的表??疾毂?-1,我們首先要找出主鍵。可以看到,屬性對<Project Number, Employee Number>是主鍵,其他所有的屬性都依賴于該主鍵。





回頁首


從一范式轉化到二范式

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

考察表1-1,我們可以發(fā)現,非主屬性<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, 我們發(fā)現插入異常已經不存在了,當我們引入一個新的項目 TPT 的時候,我們只需要向表1-2 中插入一條數據就可以了, 當有新人加入項目 TPT 的時候,我們需要向表1-3, 1-4 中各插入一條數據就可以了。雖然我們解決了一個大問題,但是仔細觀察我們還是發(fā)現有問題存在。





回頁首


從二范式轉化到三范式

考察表前面生成的三張表,我們發(fā)現,表1-3存在傳遞依賴關系,即:關鍵字段< Employee Number > --> 非關鍵字段< Salary Category > -->非關鍵字段< Salary Package >。而這是不滿足三范式的規(guī)則的,存在以下的不足:

1、 數據冗余:<Salary Category>和<Salary Package>的值有重復;

2、 更新異常:有重復的冗余信息,修改時需要同時修改多條記錄,否則會出現數據不一致的情況;

3、 刪除異常:同樣的,如果員工 200003 Kevin 離開了公司,會直接導致 Salary C 的信息的丟失。

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

因此,我們需要繼續(xù)進行規(guī)范化的過程,把表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經過規(guī)范化步驟,得到四張表,滿足了三范式的約束要求,數據冗余、更新異常、插入異常和刪除異常。

在三范式之上,還存在著更為嚴格約束的BC范式和四范式,但是這兩種形式在商業(yè)應用中很少用到,在絕大多數情況下,三范式已經滿足了數據庫表規(guī)范化的要求,有效地解決了數據冗余和維護操作的異常問題。





回頁首


結束語

在本文描述的過程中,我們通過結合實例的方法,通俗地演繹了數據表規(guī)范化的過程,并展示了在此過程中數據冗余、數據庫操作異常等問題是如何得到解決的。

在具體的工程應用中,運用數據庫規(guī)范化的方法來設計數據庫表,將是具有現實意義的。





回頁首


參考資料





回頁首


作者簡介

陳博,目前為浙江大學計算機科學與技術學院研究生一年級在讀,碩士研究方向為智能軟件工程,導師為應晶教授。


 

蔣韜,目前是 IBM 上海軟件開發(fā)中心工具開發(fā)組的軟件工程師,主要負責基于 J2EE 構架的翻譯工具的開發(fā)和整合。2004 年畢業(yè)于復旦大學計算機系, 在進入 IBM 之前一直從事構件,構架整合和工具開發(fā)方面的工作,在 J2EE, DB2, XML, Web Services, IRUP, XP 方面都有豐富的項目經驗。






回頁首


    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多