Logo

新人日誌

首頁關於我部落格

新人日誌

Logo

網站會不定期發佈技術筆記、職場心得相關的內容,歡迎關注本站!

網站
首頁關於我部落格
部落格
分類系列文

© 新人日誌. All rights reserved. 2020-present.

資料庫架構設計入門:用 PRIMARY KEY 識別每一筆資料

最後更新:2026年1月9日資料庫

前面我們介紹了第二正規化、第三正規化,還有第一正規化的後半。

現在終於要進入第一正規化的前半,也就是整個正規化形式的最開頭。

第一正規化的前半告訴我們:表單要有一個欄位是主鍵(Primary Key)。

什麼是主鍵?為什麼需要它?我們來看一個例子。

為什麼需要主鍵

假設你有一個會員表單,用「會員姓名」來識別每一筆資料:

會員姓名會員信箱
Daviddavid@mail.com
Emilyemily@mail.com
Frankfrank@mail.com
會員信箱david@mail.com
會員信箱emily@mail.com
會員信箱frank@mail.com

看起來沒問題,每個人的姓名都不一樣,可以分辨誰是誰。

但現在要新增一筆會員資料,這個人也叫 David:

會員姓名會員信箱
Daviddavid@mail.com
Emilyemily@mail.com
Frankfrank@mail.com
Davidanother.david@mail.com
會員信箱david@mail.com
會員信箱emily@mail.com
會員信箱frank@mail.com
會員信箱another.david@mail.com

問題來了:怎麼分辨這是兩個不同的 David?

如果你想修改第一個 David 的信箱,你要怎麼告訴資料庫「我要改的是第一個 David,不是第二個」?

這就是「識別資料」的問題。

用姓名識別的問題

除了「姓名可能會重複」之外,還有兩個問題。

姓名可能會改變。如果第一個 David 改名叫 Kevin 呢?

會員姓名會員信箱
Kevindavid@mail.com
Davidanother.david@mail.com
會員信箱david@mail.com
會員信箱another.david@mail.com

如果其他表單(例如會員電話表)是用「David」來關聯這個會員,現在就找不到了,因為 David 已經變成 Kevin 了。

姓名可能是空的。如果有人還沒填姓名呢?

會員姓名會員信箱
Kevindavid@mail.com
Davidanother.david@mail.com
test@mail.com
會員信箱david@mail.com
會員信箱another.david@mail.com
會員信箱test@mail.com

第三筆資料是誰?不知道,根本無法識別。

結論:用姓名來識別會員,會遇到重複、改變、空值的問題。

主鍵(Primary Key)

從上面的例子可以發現,用「姓名」來識別會員會遇到三個問題:

  • 可能會重複(兩個 David)
  • 可能會改變(David 改名叫 Kevin)
  • 可能是空的(有人還沒填姓名)

所以,我們需要一個欄位,專門用來識別「這是哪一筆資料」。這個欄位就叫做主鍵(Primary Key)。

主鍵的作用是:唯一識別每一筆資料。有了主鍵,不管你要查詢、修改、刪除哪一筆資料,都能準確找到它。

主鍵的三個條件

主鍵必須符合三個條件:

  1. 不能重複:如果重複了,就無法分辨是哪一筆
  2. 不應該改變:如果改了,其他表單原本用這個值來關聯,就會找不到資料。像前面的例子,會員電話表用「David」關聯會員,結果 David 改名成 Kevin,關聯就斷了
  3. 不能是空值:如果是空的,就不知道這是哪一筆資料

在資料庫中,你可以對某個欄位加上 PRIMARY KEY,告訴資料庫「這個欄位是主鍵」。加上之後,資料庫會自動幫你:

  • 加上 NOT NULL 限制(不能是空值)
  • 加上 UNIQUE 限制(不能重複)

另外,每張表單最多只能有一個 PRIMARY KEY。為什麼?如果有兩個主鍵,當它們的值互相衝突時,要以哪個為準?不知道。所以每張表單只能有一個主鍵,用它來唯一識別每一筆資料。

主鍵應該用什麼值?

現在問題來了:什麼欄位適合當主鍵?

姓名不適合當主鍵

姓名可能重複(兩個人都叫 David),也可能改變(改名)。

Email 不適合當主鍵

Email 可能改變(換信箱)。

用 ID 當主鍵

姓名會重複、會改變。Email 會改變。現實世界的資料,好像都不太適合當主鍵。

那怎麼辦?

既然現實世界的資料都不可靠,那就自己創造一個專門用來識別的編號。這個編號:

  • 沒有任何實際意義,純粹用來識別
  • 由系統自動產生,保證不重複
  • 永遠不會改變

這個編號通常叫做 ID(Identifier,識別碼)。這就是為什麼你會看到資料庫的表單裡,幾乎都有一個「ID」欄位,它就是拿來當主鍵用的。

流水號 vs UUID

「毫無意義的編號」有兩種常見的做法:

流水號

按順序編號,簡單易懂。

會員 ID會員姓名
1David
2Emily
3Frank
會員姓名David
會員姓名Emily
會員姓名Frank

優點:簡單、好讀

缺點:可能洩漏商業資訊

例如,如果訂單編號是流水號:

  • 月初買一次,訂單編號是 1001
  • 月底買一次,訂單編號是 1532

別人就能推算出你這個月有大約 500 張訂單,進而估算營業額。

UUID

一串看起來很亂的英文和數字,例如:f47ac10b-58cc-4372-a567-0e02b2c3d479

優點:無法從編號推測任何資訊

缺點:不好讀、佔用較多空間

流水號和 UUID 怎麼選

  • 對內使用(例如內部管理系統):流水號就可以了,簡單方便
  • 對外曝露(例如給客戶看的訂單編號):建議用 UUID,避免洩漏資訊

現在大多數資料庫都支援自動產生 UUID,不用自己想怎麼生成。

主鍵讓關聯更穩定

還記得之前的會員電話表嗎?

以前的做法(用姓名關聯):

會員表單:

會員姓名會員信箱
Daviddavid@mail.com
Emilyemily@mail.com
會員信箱david@mail.com
會員信箱emily@mail.com

會員電話表單:

電話所屬會員
0912-345-678David
0922-111-222David
所屬會員David
所屬會員David

如果 David 改名叫 Kevin,會發生什麼事?

會員表單:

會員姓名會員信箱
Kevindavid@mail.com
Emilyemily@mail.com
會員信箱david@mail.com
會員信箱emily@mail.com

會員電話表單:

電話所屬會員
0912-345-678David
0922-111-222David
所屬會員David
所屬會員David

電話表的「所屬會員」還是寫 David,但會員表裡已經沒有 David 了,變成 Kevin。關聯就斷掉了!

現在的做法(用主鍵關聯):

會員表單:

會員 ID(PK)會員姓名
U001David
U002Emily
會員姓名David
會員姓名Emily

會員電話表單:

電話會員 ID
0912-345-678U001
0922-111-222U001
會員 IDU001
會員 IDU001

現在電話表關聯的是「會員 ID」,不是姓名。

如果 David 改名叫 Kevin:

會員 ID(PK)會員姓名
U001Kevin
U002Emily
會員姓名Kevin
會員姓名Emily

電話表完全不用改!因為它關聯的是 U001,而 U001 還是那個人。

這就是主鍵的威力:其他欄位再怎麼改,都不會影響資料之間的關聯。

PRIMARY KEY 重點整理

這篇文章介紹了第一正規化的前半:

  1. 問題:怎麼識別「這是哪一筆資料」?欄位的值可能重複或改變
  2. 解法:加上主鍵(Primary Key)欄位
  3. 主鍵的條件:不能是空值、不能重複、不應該改變
  4. PRIMARY KEY 限制:自動包含 NOT NULL 和 UNIQUE,每張表最多一個
  5. 主鍵的值:建議用毫無意義的編號(流水號或 UUID)
  6. 好處:其他欄位再怎麼改,都不會影響資料之間的關聯

到目前為止,我們已經學了三種欄位限制:

  • UNIQUE:確保欄位的值不重複
  • NOT NULL:確保欄位一定要有值
  • PRIMARY KEY:確保可以唯一識別每一筆資料(包含 UNIQUE + NOT NULL)

前三個正規化形式也都介紹完了!這些原則的核心都是一樣的:讓資料庫的結構乾淨、不重複、好維護。

目前還沒有留言,成為第一個留言的人吧!

發表留言

留言將在審核後顯示。

資料庫

目錄

  • 為什麼需要主鍵
  • 用姓名識別的問題
  • 主鍵(Primary Key)
  • 主鍵的三個條件
  • 主鍵應該用什麼值?
  • 姓名不適合當主鍵
  • Email 不適合當主鍵
  • 用 ID 當主鍵
  • 流水號 vs UUID
  • 流水號
  • UUID
  • 流水號和 UUID 怎麼選
  • 主鍵讓關聯更穩定
  • PRIMARY KEY 重點整理