BCNF 拿掉 3NF「只檢查非鍵值欄位」的前提

BCNF 常被講成「比 3NF 更嚴格」,但嚴格在哪講不清楚。精確的差別只有一個前提子句。

條文
3NFX → Y 時,X 是 superkey 或 Y 是鍵值欄位
BCNFX → Y 時,X 必須是 superkey

BCNF = 3NF 刪掉那條豁免。換句話說:3NF 只在「被決定的那個欄位是非鍵值欄位」時才出手,BCNF 不管右邊是誰。

漏洞長什麼樣

排課表,每位老師只教一門課(superkey 就是能唯一指出一列的欄位組合 用的同一張表):

R(學生, 課程, 老師)
(學生, 課程) → 老師
老師 → 課程                    ← 問題在這條
候選鍵:(學生, 課程) 與 (學生, 老師)

這張表三個欄位全是鍵值欄位,一個非鍵值欄位都沒有。讓 3NF 來查:

3NF:請列出你的非鍵值欄位,我一個一個查。 這張表:我沒有非鍵值欄位。 3NF:那沒事了,通過。

它通過 3NF 不是因為乾淨,是因為 3NF 要查的東西它一個都沒有。 但表是壞的:

異常情境
修改張老師有 50 個學生,「張老師教資料庫」就被抄 50 次;轉教別科要改 50 列
新增新聘老師還沒招到學生 → 寫不進去,每列都要有學生
刪除最後一個學生退選 → 「王老師教網路」跟著消失

BCNF 抓得到,因為它只問左邊:老師 是 superkey 嗎?不是(光說張老師對到兩列)→ 違規。

修法是把那個不需要學生就成立的事實搬出去:(老師, 課程) + (學生, 老師)。

這正是 正規化的三個階段是同一個問句的三種問法 那個問句的延續 — 「這個欄位到底跟誰有關」,只是 BCNF 連鍵值欄位也一起問。代價見 BCNF 保證無損 join,但不保證保持相依。