第一正規化

第一正規化(1NF)是資料庫正規化所使用的正規形式。第一正規化是為了要排除重複群的出現,要求資料庫的每一列的论域都是由不可分割的原子值組成;每個欄位的值都只能是單一值。1971年埃德加·科德提出了第一正規化。

不符合第一正規化的情況

重複群

重複群通常會出現在會計帳上,每一筆記錄可能有不定個數的值。舉例來說:

交易
顧客 日期 數量
Pete Monday 19.00 -28.20
Pete Wednesday -84.00
Sarah Friday 100.00 150.00 -40.00

「數量」就是所謂的重複群了,而在這種情況下這份資料就不符合第一正規化。想要消除重複群的話,只要把每筆記錄都轉化為單一記錄即可:

交易
顧客 日期 數量
Pete Monday 19.00
Pete Monday -28.20
Pete Wednesday -84.00
Sarah Friday 100.00
Sarah Friday 150.00
Sarah Friday -40.00

缺乏唯一識別碼

一樣是在交易這個例子中,同一天同一個人買了同樣的數量,這樣的交易做了兩次:

交易
顧客 日期 數量
Pete Monday 19.00
Pete Monday 19.00

如上所示,這兩筆交易可以說是一模一樣,也就是說如果只靠這些資料我們沒有辦法分辨這兩筆記錄。我們之所以說它不符合第一正規化,是因為上面這樣的表示法欠缺一個唯一識別碼,可以是一個欄位,也可以是一組欄位,而且可以保證在這個資料中唯一識別碼不會重複出現。要將它正規化到符合第一正規化的原則只需要加入一個唯一識別碼即可:

交易
交易 ID 顧客 日期 數量
1 Pete Monday 19.00
2 Pete Monday 19.00

關聯式資料庫的第一正規化的讨论

重复群(repeating group)是指含有多值的一个列。原子性(atomicity)的操作语义可以说如果关系数据库管理系统的类型系统允许的值,例如date类型、VARCHAR(20)类型。严格意义上,NULL违背了第一范式;通常把NULL理解为标记(marker),而不是值(value),用专门的函数、运算符去处理NULL。

第一范式意味着:表中没有重复的行、重复的列;不存在行序、列序。

從某個角度看來,不允許重複群的出現是關聯式資料庫表示資訊的方法,RDBMS 裡資料表每一筆記錄的每一個欄位都只能是单个的原子值。舉例來說,如果定義了一個叫做 Favorite Number 的整數欄位,每一筆記錄的 Favorite Number 這個欄位都只會是一個整數 (或是無);這也就是說,如果設定了主鍵的話,理論上不可能會有任何關聯式資料庫的資料表會違反第一正規化的原則。

不過就算是在這種情況下,還是可以設計出在骨子裡違反第一正規化的資料表。最簡單的方法就是把多個有意義的值編碼過後存進一個欄位裡,然後在資料表中用很多欄位來表達同一個事實。

單一欄位中有多個有意義的值

在單一欄位中存放多個值是違反第一正規化的做法,下面這個就是很好的例子,它把多個值用逗號分開來表示:

挑食列表
不喜歡的食物
Jim Liver, Goat's cheese
Alice Broccoli
Norman Pheasant, Liver, Peas

以這樣的設計看來,想要知道有什麼人不喜歡某樣特定的東西是很不容易的。不過可以把這個資料表轉化成下面這種符合第一正規化的型式:

挑食列表
不喜歡的食物
Jim Liver
Jim Goat's cheese
Alice Broccoli
Norman Pheasant
Norman Liver
Norman Peas

用很多欄位來表達同一個事實

在同一個資料表裡用多個欄位來表達同一個事情也是違反第一正規化的:

個人資料
喜歡的顏色 不喜歡的食物 (1) 不喜歡的食物 (2) 不喜歡的食物 (3)
Jim Green Liver Goat's cheese
Alice Fuchsia Broccoli
Norman Blue Pheasant Liver Peas
Emily Yellow

就算我們能確定每個人不喜歡吃的食物最多不會超過三樣,這還是一個很糟的設計。舉例來說,我們想要知道所有不喜歡同一種食物的人的組合的話,這就不是件容易的事,因為食物有可能出現在任何一個欄位,也就是說每一次的查詢都要去檢查 9 (3 x 3) 組不同的欄位組合。

参见

参考文獻

外部連結