簡體   English   中英

為什么不允許表中有兩個主鍵?

[英]Why two primary keys in a table is not allowed?

我想了解MySql語法為什么不允許在同一表中使用兩個主鍵的原因。 我了解復合鍵,與此無關。

我不明白為什么不允許在同一表中使用兩個單獨的主鍵。 但是我們可以將一列作為主鍵,將另一列作為唯一鍵而不是null。 實際上,它具有兩個不同的主鍵,因為我們可以使用這些鍵中的任何一個來清楚地標識行。 為什么第一個不允許,但第二個不允許?

我試圖弄清楚邏輯,但偶然發現了科德12條規則中的規則2,

通過使用表名,主鍵值和列名的組合,可以確保邏輯上可以訪問關系數據庫中的每個數據(原子值)。

表名稱,主鍵值和列的組合對於單個基准值是否應該是唯一的,或者我們可以有多種組合來保證訪問? 為什么或者為什么不?

編輯:由於該問題被確定為可能的重復,我將在下面解釋它的不同之處其他類似的問題是

我可以在一個表中有多個主鍵嗎?

答案是

我的問題是為什么 這是什么原因?

根據第2條規則,科德打算說什么?

如果允許多個單獨的主鍵會發生什么問題?

你可以有許多獨特KEY約束作為數據庫系統允許,和許多關系較真現在看到它作為一個錯誤來提升這些關鍵之一 ,並膏抹為PRIMARY。

從邏輯上講,唯一鍵約束和主鍵都實現相同的目的-定義列的子集,通過該列子可以唯一地標識行。 它們還應該有資格作為外鍵約束的目標。

某些默認設置(例如可空性)由主鍵約束自動應用,但是沒有理由不能將相同的約束手動應用於唯一鍵約束中包含的列。

“主鍵”可以追溯到關系模型的發明者Ted Codd ,后者是基於SQL的松散基礎。 Codd清楚地意識到,當關系作為變量(relvar,r-table,table等)存儲在DBMS中時,它可能具有多個應強制使用的候選鍵。 他最初認為提名一個或多個鍵為“主鍵”可能是有益的。 從那時起(1960年代末!),RM的思維不斷發展,“主鍵”的想法不再被認為具有潛在的益處。 關於空值,可以說類似的話:Codd繼續提出兩種類型的空值,即四值邏輯。 我能說什么 這個人是個天才,但並非萬無一失!

令人遺憾的是,許多早期的RM思想使它融入了早期的SQL實現中,並隨后被納入SQL標准中。 並且由於“兼容性問題”,它們將永遠不會從SQL標准中刪除。 但是這些事情沒有在SQL中正確實現。 例如,Codd沒有指定relvar應該限制為一個主鍵,但是在SQL中實現時,現在每個表一個規則。 為什么? 早期的SQL實現者對Codd的原始論文有誤解嗎? 關系理論家的巧妙設計嗎? 我認為是陰謀大忌!

PK和等效的NOT NULL UNIQUE約束之間的差異很小,並且不是非常有用。 例如,在SQL中指定PK時,必須指定被引用的表,但是可以省略引用列。 指定列時,它們必須“等於引用表的唯一約束的唯一列中的列名集”(即PK或任何NOT NULL UNIQUE約束)。 當從定義中刪除列時,則假定引用表的PK。 如果一個表被允許具有多個PK,那么此功能實際上將不起作用。 正如我所說,這並不重要,但對於某些用戶而言可能很重要。

主鍵具有三個屬性:

  • 值的組合是唯一的。
  • 鍵中的每個值NOT NULLNOT NULL
  • 每個表只有一個主鍵。

一個表可以具有滿足前兩個條件的鍵或鍵組合。 您在問為什么需要第三個定義。

為了方便定義關系邏輯,每個表都具有訪問特定行的“命名”方法。 例如,這為如何最好地定義外鍵關系(使用主鍵)提供了指導。 這只是定義。

某些數據庫使用主鍵對數據進行聚類,即對數據頁上的行進行排序。 鑒於只能以一種方式對數據進行排序,因此提供了一個實際的理由。

從規范化的角度

數據庫算法背后有很多計算機科學,就像任何科學都必須做出假設一樣,其中之一是數據以規范化的形式存儲。 該行中的所有內容都必須取決於鍵(第一標准格式), 整個鍵(第二標准格式),並且取決於鍵(第三標准格式)。 當您偏離這一點時,您將獲得較少的可預測性,並且通常性能較差。

行可以具有任意數量的候選鍵 ,每個候選鍵都可以滿足成為主鍵的條件。 我想您可以將其他人稱為“第二把鑰匙”或“第三把鑰匙”。 真的沒有人這樣做。 如果需要另一個值,例如自然鍵 ,通常將其設置為屬性,而不是鍵。

話雖如此,您可以將任意兩列稱為復合鍵 ,也可以將該鍵聲明為主鍵。 這樣,確實有兩列參與主鍵關系。 但這會導致性能問題。

從性能角度看

一個密鑰對於實現規范化架構是必要且足夠的。 可以設置多個密​​鑰,但是它們將包含冗余數據(如果您知道一個,就知道另一個,如果您知道向誰詢問),並且違反了第二種標准格式。 這也意味着每一行將占用它真正需要的更多空間。 較大的行意味着每頁較少的行,這意味着性能較差,特別是考慮到主鍵用作集群鍵,並且包含在整個數據庫中所有索引的葉頁中。 為什么將字節花在您已經知道的事情上?

典型做法

將任何其他“鍵”作為屬性存儲在定義實體的行中。 例如,您可以將社會保險號存儲為Employee表的屬性,其中EmployeeID是主鍵(並且可能是代理鍵)。 無論何時需要,都可以連接到Employee表。 (順便說一句,您可能想加強SSN的列級權限。)不要將其存儲在多個位置; 沒必要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM