示例表數據
假設有一個名為employee
的員工表,它有九個屬性:id
(員工編號)、name
(員工名稱)、mobile
(電話)、zip
(郵編)、province
(省份)、city
(城市)、district
(區縣)、deptNo
(所屬部門編號)、deptName
(所屬部門名稱)、表總數據如下:
id | name | mobile | zip | province | city | district | deptNo | deptName |
---|---|---|---|---|---|---|---|---|
101 | 張三 | 13910000001<br />13910000002 | 100001 | 北京 | 北京 | 海淀區 | D1 | 部門1 |
101 | 張三 | 13910000001<br />13910000002 | 100001 | 北京 | 北京 | 海淀區 | D2 | 部門2 |
102 | 李四 | 13910000003 | 200001 | 上海 | 上海 | 靜安區 | D3 | 部門3 |
103 | 王五 | 13910000004 | 510001 | 廣東省 | 廣州 | 白云區 | D4 | 部門4 |
103 | 王五 | 13910000004 | 510001 | 廣東省 | 廣州 | 白云區 | D5 | 部門 5 |
由于此員工表是非規范化的,我們將面對如下的問題。
修改異常:上表中張三有兩條記錄,因為他隸屬于兩個部門。如果我們要修改張三的地址,必修修改兩行記錄。假如一個部門得到了張三的新地址并進行了更新,而另一個部門沒有,那么此時張三在表中會存在兩個不同的地址,導致了數據不一致
新增異常:假如一個新員工假如公司,他正處于入職培訓階段,還沒有被正式分配到某個部門,如果
deptNo
字段不允許為空,我們就無法向employee
表中新增該員工的數據。刪除異常:假設公司撤銷了D3部門,那么在刪除
deptNo
為D3的行時,會將李四的信息也一并刪除。因為他隸屬于D3這一部門。
第一范式(1NF)
表中的列只能含有原子性(不可再分)的值。
表中的張三有兩個手機號存儲在mobile列中,違反了 1NF 規則。為了使表滿足 1NF,數據應該修改如下:
id | name | mobile | zip | province | city | district | deptNo | deptName |
---|---|---|---|---|---|---|---|---|
101 | 張三 | 13910000001 | 100001 | 北京 | 北京 | 海淀區 | D1 | 部門1 |
101 | 張三 | 13910000002 | 100001 | 北京 | 北京 | 海淀區 | D1 | 部門1 |
101 | 張三 | 13910000001 | 100001 | 北京 | 北京 | 海淀區 | D2 | 部門2 |
101 | 張三 | 13910000002 | 100001 | 北京 | 北京 | 海淀區 | D2 | 部門2 |
102 | 李四 | 13910000003 | 200001 | 上海 | 上海 | 靜安區 | D3 | 部門3 |
103 | 王五 | 13910000004 | 510001 | 廣東省 | 廣州 | 白云區 | D4 | 部門4 |
103 | 王五 | 13910000004 | 510001 | 廣東省 | 廣州 | 白云區 | D5 | 部門 5 |
第二范式(2NF)
第二范式要同時滿足下面兩個條件
滿足第一范式
沒有部分依賴
例如,員工表的一個候選鍵是{id,mobile,deptNo},而deptName依賴于deptNo,同樣 name 依賴于 id,因此不是 2NF的。為了滿足第二范式的條件,需要將這個表拆分成employee、dept、employee_dept、employee_mobile四個表。如下:
員工表 employee
id | name | zip | province | city | district |
---|---|---|---|---|---|
101 | 張三 | 100001 | 北京 | 北京 | 海淀區 |
102 | 李四 | 200001 | 上海 | 上海 | 靜安區 |
103 | 王五 | 510001 | 廣東省 | 廣州 | 白云區 |
部門表 dept
deptNo | deptName |
---|---|
D1 | 部門1 |
D2 | 部門2 |
D3 | 部門3 |
D4 | 部門4 |
D5 | 部門5 |
員工部門關系表 employee_dept
id | deptNo |
---|---|
101 | D1 |
101 | D2 |
102 | D3 |
103 | D4 |
104 | D5 |
員工電話表 employee_mobile
id | mobile |
---|---|
101 | 13910000001 |
101 | 13910000002 |
102 | 13910000003 |
103 | 13910000004 |
第三范式(3NF)
第三范式要同時滿足下面兩個條件
- 滿足第二范式
- 沒有傳遞依賴
例如,員工表的province、city、district依賴于zip,而zip依賴于id,換句話說,province、city、district傳遞依賴于id,違反了 3NF 規則。為了滿足第三范式的條件,可以將這個表拆分成employee和zip兩個表,如下
employee
id | name | zip |
---|---|---|
101 | 張三 | 100001 |
102 | 李四 | 200001 |
103 | 王五 | 510001 |
地區表area
zip | province | city | district |
---|---|---|---|
100001 | 北京 | 北京 | 海淀區 |
200001 | 上海 | 上海 | 靜安區 |
51000 | 廣東省 | 廣州 | 白云區 |
在關系數據庫模型設計中,一般需要滿足第三范式的要求。如果一個表具有良好的主外鍵設計,就應該是滿足3NF的表。規范化帶來的好處是通過減少數據冗余提高更新數據的效率,同時保證數據完整性。然而,我們在實際應用中也要防止過度規范化的問題。規范化程度越高,劃分的表就越多,在查詢數據時越有可能使用表連接操作。而如果連接的表過多,會影響查詢性能。關鍵的問題是要依據業務需求,仔細權衡數據查詢和數據更新關系,指定最合適的規范化程度。不要為了遵循嚴格的規范化規則而修改業務需求。