數據庫設計三范式(NF)之第一范式極簡說明
一句話核心思想
第一范式就是:表中的每個字段都是不可再分的“原子”值。
換句話說,表中的每一列都應該只包含單一的值,而不能是值的集合、數組或者可以再拆分的復合值。
用一個生動的例子來解釋
想象一下,我們要設計一張 訂單表。
錯誤的設計(違反第一范式):
| 訂單號 | 顧客姓名 | 商品 |
|---|---|---|
| 1001 | 張三 | iPhone, AirPods |
| 1002 | 李四 | iPad, Pencil |
這張表有什么問題?
-
商品列 包含了多個值(“iPhone, AirPods”)。這違反了1NF。 -
這會導致很多麻煩:
-
查詢困難:很難寫一個查詢來找出所有包含了“AirPods”的訂單。
-
更新困難:如果李四想把“Pencil”換成“Keyboard”,操作會很復雜,容易出錯。
-
統計困難:無法簡單地統計每個商品被賣出了多少次。
-
另一個常見的錯誤設計:
| 訂單號 | 顧客姓名 | 聯系方式 |
|---|---|---|
| 1001 | 張三 | 電話:13800138000 |
| 1002 | 李四 | 郵箱:lisi@email.com |
-
聯系方式列 包含了類型和具體值兩個信息,它可以被拆分成“聯系類型”和“聯系值”兩列。這也違反了1NF。
如何改造?(使其符合第一范式)
核心操作:把復合值或多值拆分成“原子”值。
對于上面的 訂單表,我們有幾種符合1NF的設計方法:
方法一:使用多行表示(經典方法)
將多個商品拆分成多條獨立的記錄。
| 訂單號 | 顧客姓名 | 商品 |
|---|---|---|
| 1001 | 張三 | iPhone |
| 1001 | 張三 | AirPods |
| 1002 | 李四 | iPad |
| 1002 | 李四 | Pencil |
現在,商品列的每一個單元格都只包含一個不可再分的值。它滿足了第一范式。
方法二:拆分列(如果值是固定的、有限的)
如果商品數量固定(例如,一個訂單最多只能買3件商品),可以拆分成多個列。(這種方法不常用,靈活性差)
| 訂單號 | 顧客姓名 | 商品1 | 商品2 | 商品3 |
|---|---|---|---|---|
| 1001 | 張三 | iPhone | AirPods | NULL |
| 1002 | 李四 | iPad | Pencil | NULL |
這種方法雖然每個單元格都是原子值,但會產生很多空值(NULL),并且擴展性很差(如果規則變成最多買5件商品,就要改表結構),所以不是最佳實踐。
對于 聯系方式表,我們可以這樣改:
| 訂單號 | 顧客姓名 | 聯系類型 | 聯系值 |
|---|---|---|---|
| 1001 | 張三 | 電話 | 13800138000 |
| 1002 | 李四 | 郵箱 | lisi@email.com |
現在,每一列都是原子值。
為什么第一范式如此重要?
1NF是數據庫設計的基石。沒有它,后續的范式(2NF, 3NF, BCNF)都無從談起。它確保了數據的基本結構是規整的,從而使得:
-
數據操作變得簡單:可以使用標準的SQL語句(如
WHERE 商品 = 'AirPods')進行精確查詢、更新和刪除。 -
維護數據一致性:避免了在一個字段內修改部分數據帶來的不一致風險。
-
為后續規范化打好基礎:只有滿足了1NF,我們才能清晰地分析字段之間的依賴關系,進而進行第二、第三范式的優化。
總結
第一范式(1NF)的要求非常簡單粗暴:
-
每一列都是單一的、不可再分的數據項。
-
每一行和每一列的交匯點(單元格)有且只有一個值。
-
同一列中的所有值必須是同一數據類型。
你可以把它想象成Excel表格的最佳實踐:一個單元格里只填一個內容,不要用逗號隔開一堆東西。 這是所有數據庫設計的第一步,也是最基本的一步。

浙公網安備 33010602011771號