2010-04-19 52 views
19

爲什麼拒絕組合鍵有利於使用名爲id的單個主鍵的所有表?因爲通常所有的ORM都遵循這一點。爲什麼單個主鍵優於組合鍵?

編輯

我剛開始在軌道上,並通過務實的書敏捷開發的學習Ruby有一行:--- Rails的真不工作也很好,除非每個表都有一個數字首要的關鍵。對列的名稱不那麼挑剔。 我在學習教義時讀到的同一種線條。

EDIT2 請檢查此鏈接。我越來越感到困惑這事--- Composite primary keys versus unique object ID field

從上面的鏈接: -

*主鍵應該是恆定的,毫無意義;非代理鍵通常會失敗一個或兩個要求,最終

如果密鑰不是恆定的,那麼將來的更新問題可能會變得非常複雜 如果密鑰沒有意義,那麼它更有可能發生更改,即不是恆定的;見上面

以一個簡單的常見示例:一個庫存項目表。將物品編號(SKU編號,條形碼,零件代碼或其他)作爲主鍵可能會很誘人,但一年後所有物品編號都會發生變化,並且會留下一個非常混亂的更新 - 整體 - 數據庫問題...

編輯:還有一個問題比哲學更實用。在很多情況下,你會以某種方式找到特定的行,然後再更新它或再次找到它(或兩者)。使用組合鍵時,需要跟蹤更多的數據並在WHERE子句中使用更多的約束來重新查找或更新(或刪除)。其中一個關鍵細分也可能在此期間發生變化!與代理鍵,總有隻有一個保留(替代ID)和根據定義,它不能改變,這顯著簡化了的情況的值。*

+3

請引用你的來源?我同時使用:複合鍵和基於序列的ID主鍵。有時候一個比另一個更合適。 – FrustratedWithFormsDesigner 2010-04-19 14:08:52

+0

你在使用哪個ORM,它總是使用複合鍵上的簡單鍵?我從來沒有遇到過使用組合鍵不能很好地發揮作用的ORM。據我所知,沒有很好的理由給例如一個聯結表是它自己的代理鍵。 – 2010-04-19 15:42:42

+0

@FrustratedWithFormsDesigner @Iain Galloway 我在學習Doctrine的同時閱讀了這篇文章,現在我在rails上學習Ruby時遇到了同樣的情況。 讓我知道如果你想要的書的確切頁碼在哪裏寫這行。我是初學者所以我要求真實的東西。不要在此問題上交叉提問或辯論。意味着他們爲什麼使用這個ID字段。 ?? – 2010-04-20 13:28:13

回答

21

我不認爲有一個你應該只使用一個名爲id的主鍵的總括性聲明。

大多數人使用代理主鍵作爲自動生成int,因爲它將主鍵從需要更改的位置隔離開來,就像您將PK用作用戶名並且後來更改其合法名稱一樣。您將不得不更新PK和所有FK列以反映新名稱。如果您使用了代理主鍵,則只需在一個地方更新用戶的名稱(因爲這些表聯接int而不是名稱)。

主鍵的大小非常重要,因爲PK會複製到您在表上構建的每個索引中。如果PK很大(比如一個字符串),那麼索引中每個頁面的鍵值就會更少,並且索引將需要更多的高速緩存來存儲它。 Ints很小。

有一個自動增量int PK本身就是一個聚集索引,因爲行以這種順序存儲,並且不需要返回並且不需要插入新行來增加行,所以總是添加到桌子的盡頭。

+0

順序GUID也能很好地工作,尤其是當您需要將來自多個數據庫的數據集合併到一個表中時。 – Juliet 2010-04-19 14:17:47

+0

@Juliet,但它們很大並且浪費索引空間。如果可能的話,最好將自動增量int ID與另一列組合起來,並標識數據庫/公司/ etc(如1或2個字節的int),因爲它可以使用比guid少得多的空間,但仍然在所有數據庫中是唯一的。 – 2010-04-19 14:20:54

+4

我不會推薦使用GUID除邊緣情況下 – 2010-04-19 14:32:30

1
  1. 爲了識別 柱用的ORM單一致的名稱如 table_id比複合鍵 更容易。但是每個好的ORM都支持 複合鍵。

  2. 一個簡單的PK可以很容易地被數據庫'自動增加' '。 這不適用於複合 鍵。

  3. 簡單的PK在 查詢中也更容易使用。當你需要加入時,你只需要使用 關係中的一列。

這並不是說簡單的PKs比複合材料更好。

7

您可以同時使用兩者。在某些情況下,當您在實體之間建立關聯時,您可以將兩個實體鍵用作組合鍵。

作爲一個經驗法則,我使用生成的實體和組合鍵作爲關係。

+0

這與我使用的方法相同,並且工作得很好。 – 2015-03-24 16:55:19

0

面向對象編程中的對象具有標識,無論其內容如何。關係數據庫中的行(元組)僅由其內容標識。所以當真正做ORM時,即將對象從面向對象的編程語言映射到關係數據庫時,必須提供一個額外的ID,以區分該對象在程序中的字段和/或屬性 - 除非其中一個或多個是以某種方式知道唯一識別對象。

+0

你當然需要在你的表上有一個*主鍵*,但沒有理由必須是單個列。複合主鍵非常常見,尤其是在聯結表上。 – 2010-04-19 15:36:55

+0

請再讀一遍。我沒有說主關鍵字在關係數據庫模式中是必需的(他們沒有),也沒有在設計關係數據庫模式時出現這種組合關鍵字(他們這樣做)。我只想說,如果您的關係數據庫模型是從OO類模型盲目生成的,則所有表都需要具有代理ID作爲它們的主鍵,這些主鍵與對象類的任何屬性都不對應。除非以特殊方式處理集合值屬性,否則不會生成連接表。 – reinierpost 2010-04-20 15:18:06

+0

您是否有特殊的方式來表示m:m關係而不使用聯結表? – 2010-04-22 07:38:56

4

嗯,這是基本上是關於保持JOIN的簡單 - 哪一個更容易理解:

SELECT 
    p.ID, p.Name, p.City, 
    c.ID, c.Country, c.ISOCode 
FROM 
    dbo.Parent p 
INNER JOIN 
    dbo.Child c on c.ParentID = p.ID 

SELECT 
    p.ID, p.Name, p.City, 
    c.ID, c.Country, c.ISOCode 
FROM 
    dbo.Parent p 
INNER JOIN 
    dbo.Child c ON c.ParentName = p.Name 
    AND c.ParentCity = p.City 
    AND c.ParentCountry = p.Country 

如果你有複合主鍵,任何人從孩子加入到表表必須「拖動」所有這些列,並且所有這些列也將出現在子表中,並且JOIN語句非常混亂。爲JOIN提供單個(甚至是代理)密鑰更好!

+0

您是否建議使用代理鍵(而不是複合鍵)作爲表示多關係的聯結表的PK?如果是這樣,爲什麼? – 2010-04-20 11:50:30

+0

@Iain Galloway:不一定 - 多對多關係的聯結表是您可能使用複合PK來獲得優勢的特例之一。但是,即使在這種情況下添加代理PK也沒有什麼壞處(除了額外的列) - 它可以讓您更容易地管理(例如刪除)來自聯結表的條目 – 2010-04-20 12:17:11

12

我遇到的使用複合鍵的唯一實際限制就是在子查詢中使用IN表達式。這是一個問題,因爲IN表達式中的子查詢必須返回一列(至少在T-SQL中)。

SELECT 
    emp.Name, 
    emp.UserDomain, 
    emp.UserID 
FROM 
    employee emp 
WHERE 
    ???? IN (SELECT e.UserDomain, e.UserID FROM ... /* some complex 
                 non-correlated subquery 
                 or CTE */ 
      ) 

當然總會有解決方法,但有時候這可能是一個煩惱。

這是很難避免使用合成密鑰的理由。

0

您的問題與surrogate (or artificial) keys vs natural keys替代方案密切相關。我認爲這不是複合鍵少用,但自然鍵(是他們複合或簡單)不如人工鍵的青睞。

傳統的關係數據庫理論主要涉及「自然」鍵(從業務領域的角度來看具有意義的鍵),在這種情況下,複合鍵經常被發現......自然。但是在以後的幾年裏,數據庫設計有利於(儘管不是唯一的)「人造」(代理)關鍵模式,典型地是沒有商業意義的連續數字,僅用於唯一地標識表中的記錄(也許是上層的對象)。

+1

使用代理鍵時仍然可以「自然」找到複合鍵。代理對自然鍵是一個完全獨立的辯論! – 2010-04-19 15:38:17

+0

閱讀問題:「爲什麼拒絕組合鍵有利於使用名爲id的單個主鍵的所有表」。 「單個主鍵名爲id」恰恰是代理鍵。 – leonbloy 2010-04-19 15:57:40

+1

我仔細閱讀了這個問題。他根本沒有提到自然鑰匙。辯論(自然vs代理,簡單vs複合)是完全獨立的。在沒有自然鍵的情況下,複合鍵經常發生。有關相關示例,請參閱http://megocode3.wordpress.com/2008/01/04/understanding-a-sql-junction-table/你能否想到一個很好的理由將該交接表作爲自己的代理鍵? – 2010-04-19 16:24:54

2

我在一個帶有11列主鍵的應用程序上工作。每次我想保證我正在更新一行時,重複輸入列表總是很有趣。這是一個錯誤的驅動程序,MS-Access無法應對PK中的超過10列等。

大型組合鍵是設計氣味,意味着該表具有異質實體,或者設計師不確定這對每個實體來說都是獨一無二的。 (比如假設頭髮的顏色,眼睛的顏色和體重應該足以獨特地識別一名僱員 - 這不是一個好的關鍵,因爲你需要越來越多的專欄來使其工作,最終將包括字段這是揮發性和變化很多,如重量,或對一些人的頭髮顏色或缺乏那裏。)

0

雖然我同意其他受訪者給出的大多數原因,我喜歡單列整數關鍵在於它使得編寫用戶界面變得非常容易。

如果您使用某種列表控件來表示您的數據(列表,列表視圖,組合框等),則可以通過與該項目一起存儲的單個整數值將每個條目唯一地關聯到其數據庫表示。大多數預先編寫的組件已經允許您爲每個項目附加一個整數,對於那些不需要的項目,擴展組件的操作非常容易。

如果您要在服務器應用程序和網頁之間傳遞數據,將單個標識值存儲在表示數據的小部件的id屬性中比將多個值編寫和解析要容易得多IDS。