不要使用業務鍵作為資料庫主鍵

banq發表於2024-06-10


Mark Seemann這篇部落格文章反對使用自然鍵作為資料庫表中的主鍵,而是建議始終使用合成(人工)鍵。

什麼是自然鍵
自然鍵(也稱為業務鍵或領域鍵 )是資料庫中一種唯一鍵,由存在並在資料庫外部世界(即業務領域或論域)中使用的屬性組成。[3]在關係資料模型中,自然鍵是超鍵,因此是關係中所有屬性的 功能決定因素。

自然鍵有兩個互補的用途:

  • 它為資料提供了唯一的標識方法
  • 它施加一條規則,特別是唯一性約束,以確保資料在資訊系統中保持唯一性

自然鍵不同於代理鍵,後者在資料庫之外沒有任何意義,不基於現實世界的觀察,也不旨在作為對所建模現實的陳述。因此,自然鍵提供了一定的資料質量保證,而代理鍵則沒有。資料元素通常有多個鍵,其中任意數量的鍵可以是自然鍵或代理鍵。

原文觀點:
我目前正在學習資料庫和資訊系統的本科課程。由於這門課程面向沒有實際經驗的學生,因此它明智地按照教學進度進行。為了教授資料庫鍵,它從自然鍵開始。

從教學角度來看,這是有道理的,到目前為止,與我一起工作的年輕人現在提出使用自然鍵進行資料庫設計。

我沒有責怪任何人。你必須先學會爬,然後才能走路。

然而,這種情況讓我思考以下問題:自然鍵是否是一個好主意?

讓我們考慮一個例子。對於我們正在做的一個小專案,我們建立了一個世界 50 家最佳餐廳的資料庫。我的同學建議採用這樣的表格設計:

CREATE TABLE Restaurants (
    year TEXT NOT NULL,
    rank TEXT NOT NULL,
    restaurantName TEXT NOT NULL,
    cityName TEXT NOT NULL
);

當然,在這一點上,這個表格定義根本沒有定義任何鍵。我對此並無怨言。畢竟,一個月前,學生們可能還沒見過資料庫表。

不過,根據課程設定,為 Restaurants 表定義一個由 restaurantName、cityName 和 year 組成的鍵是很自然的。假設名稱和城市可以唯一標識一家餐館。

在這個特殊的例子中,這個假設可能真的成立。到此為止。畢竟,資料集並不算大,而且對於該州中的餐廳來說,擁有可識別的名稱非常重要。如果讓我猜,世界上可能只有一家 Nobelhart & Schmutzig。

不過,一個好的軟體架構師還是應該對基本假設提出質疑

  • 名字和城市是天然的關鍵嗎?

很容易想象這不是。
  • 如果我們把關鍵字擴充套件到國家這個欄位呢?

好吧,但如果我們在美國斯普林菲爾德開了一家名為 "China Wok "的餐館呢?
很難說是獨一無二的。
  • 如果再加上州呢?

可能還是不唯一的。

標識
確保唯一性只是自然鍵眾多問題中的第一個。你可能很快就會得出結論,對於餐廳資料庫來說,合成鍵可能是最好的選擇。

那麼 "自然 "的自然鍵呢?

  • 汽車底盤編號就是一個例子。這已經是一個不透明的數字,而且很可能來自某個資料庫。
  • 那麼個人身份號碼呢?在丹麥,我們有 CPR 號碼,據我所知,美國的社會安全號碼也大致類似。

如果你正在設計的資料庫已經包含了這樣一個個人身份號碼,你可能會傾向於使用它作為自然鍵。畢竟,它在其他地方已經是一個鍵了,所以可以保證是唯一的,不是嗎?

  • 是的,這個身份號碼可以唯一地識別一個人,但反過來就不一定了。
  • 一個人可能有不止一個識別碼。至少當時間是一個因素時是這樣。

例如,由於技術和歷史原因,丹麥的 CPR 號碼帶有個人出生日期和性別等資訊(按鍵不應該帶有這些資訊)。自 2014 年起,一項新的法律允許變性公民獲得一個新的 CPR 號碼,以反映他們所認為的性別。這樣做的後果是,同一個人可能擁有不止一個 CPR 號碼。也許不會同時擁有一個以上,但一生中肯定會擁有兩個。

即使現有的鍵保證是唯一的,你也不能假定唯一性會導致雙射。如果使用外部唯一鍵,就可能無法跟蹤要跟蹤的實體。

這不僅適用於人,也適用於汽車、腳踏車(也有底盤編號)、網路卡等。

資料錄入錯誤
最後,即使你已經找到了一個自然鍵,它可以保證是唯一的,並且可以跟蹤你想要跟蹤的實際實體,但還有一個反對在系統中使用外部定義鍵的理由:

  • 資料錄入錯誤。

就拿我的汽車底盤編號來說吧:
雖然我住在哥本哈根,大部分時間都是步行或騎腳踏車在城裡轉悠,但我還是擁有一輛老爺車,以便在國內其他地方代步。在丹麥,汽車每隔一年就要接受一次強制性的官方檢查,我一生中也經歷過幾次這樣的檢查。幾年前,負責檢查的機械師告訴我,我的汽車底盤編號有誤。

這確實讓我有點緊張,因為我買的是二手車,我突然擔心事情並不像我想的那樣。難道我無意中買了一輛贓車?

但機械師只是走到他的電腦前更正了錯誤。這時,一種不同的不安襲上心頭。當你從事程式設計工作幾十年後,你就會學會預見各種典型的故障模式。由於底盤編號是自然鑰匙的一個明顯候選項,我已經預料到更改這個編號要麼被證明是不可能的,要麼會產生各種連鎖反應,最終導致官方記錄不再承認這輛車是我的。

但事實證明,不管是誰製作了那款軟體,他們都知道自己在做什麼,因為機械師只是更改了底盤編號,僅此而已。現在這已經是五六年前的事了,我仍然擁有同一輛車,官方的所有權記錄也從未出現過任何問題。

發現汽車底盤編號錯誤的機械師將其明確解釋為筆誤(資料輸入錯誤)


經過幾十年的程式設計生涯,我認識到資料遲早會出錯。

  • 要麼是筆誤,
  • 要麼是終端使用者輸入錯誤,
  • 要麼是從外部系統匯入時出現資料轉換錯誤。
  • 甚至是同一系統內的資料轉換錯誤,因為它要經歷升級和遷移。

關鍵點:

  • 系統的設計應允許對資料進行更正。這包括外部鍵的更正,如底盤編號、政府 ID 等。
  • 這就意味著您不能在自己的系統中使用這些鍵作為資料庫鍵

結論:
無論您認為自然鍵有多穩定,它都可能發生變化,從而導致更新異常和完整性問題。

自然鍵對於資料庫設計來說從來都不是一個好主意,而應該始終使用資料庫生成的合成(人工)鍵作為主鍵。


 

相關文章