2011-07-22 76 views
5

我想知道'多對兩'的關係。孩子可以與兩個父母中的任何一方聯繫,但不能同時聯繫兩方。有什麼辦法可以強化這個嗎?另外我想防止孩子重複輸入。'多對兩'的關係

現實世界的例子是電話號碼,用戶和公司。公司可以有許多電話號碼,用戶可以有許多電話號碼,但理想情況下,用戶不應該提供與公司相同的電話號碼,因爲在數據庫中會有重複的內容。

+1

在你的「真實世界」的例子中,在電話號碼列上放一個UNIQUE約束不是更好嗎? – David

+1

這似乎是虛假的。如果一個孩子只與父母有關,而且只與他們中的一個有關,那麼它是多對一的。 – Patrick87

+1

等一下 - 我在一個呼叫中心工作,我們都有相同的電話號碼,至少就外部世界而言,所以如果我必須填寫訂單,並且我的同事必須填寫一個我們必須提供相同的電話號碼,因爲這是貴公司給我們打電話的內容。 – David

回答

5

這是個不錯的問題。我不明白爲什麼有人讓你失望。 (所以我標記了你,因爲我們都在這裏學習)。無論如何,這個問題表明你不完全理解實體關係(沒有粗魯的意圖)。其中有四個(技術上僅3)類型下:

 
One to One 
One to Many 
Many to One 
Many to Many 

一對一(1:1): 在這種情況下一個表已被分成兩個部分用於與正常化遵守的目的,或更通常的開放封閉原則。

Normalisation compliance:您可能有一個業務規則,即每個客戶只有一個帳戶。從技術上講,在這種情況下,你可以說客戶和賬戶都可以在同一個表中,但是這違反了規範化的規則,所以你將它們分開並做成1:1。

​​compliance:客戶表,可能有ID,第一個&姓氏和地址。稍後有人決定添加一個出生日期,並有計算年齡的能力以及其他一些非常需要的領域。這是一對一的簡單例子,但主要用於擴展數據庫而不破壞現有代碼。寫的很多代碼(可悲)與數據庫緊密耦合,所以表結構的變化會破壞代碼。像這樣添加1:1將擴展表以滿足新的要求,而無需修改原始的,從而允許舊代碼繼續正常運行,並使用新代碼來使用新的db功能。

以這種方式使用1:1關係進行規範化和擴展表的缺點是性能。通常在使用率較高的系統上,提高數據庫性能的第一個目標是將規範化並將這些表組合到一個表中,並優化索引,從而消除使用連接和從多個表中讀取的需要。歸一化/去歸一化既不是好事也可能是壞事,因爲它取決於系統的需求。大多數系統通常在需要時開始標準化,但如果代碼與DB結構緊密耦合,這種更改需要非常仔細地進行,這幾乎肯定會導致系統失敗。即當你合併兩個表時,一個不再存在,所有代碼包括現在不存在的表失敗,直到它被修改爲止(以db爲單位,想象一下將關係連接到1:1中的任何表,當你刪除這些表時,這打破了這種關係,所以必須對結構進行大幅修改才能進行補償。不幸的是,在大多數情況下,這種不好的設計在數據庫世界中比在軟件世界中要容易得多,並且通常不會注意到代碼出現問題,直到它們全部崩潰),除非系統設計正確並且考慮到separation of concerns

它是您在面向對象編程中最接近繼承的東西。但它不完全相同。

一對多(1:M)/多對一(M:1): 這兩個關係(hense爲什麼4成爲3),是最熱門的關係類型。他們都是同一類型的關係,唯一改變的就是你的觀點。一個例子一個客戶有很多電話號碼,或者許多電話號碼可以屬於一個客戶。

在面向對象的編程中,這將被視爲組合。它不是繼承,但你說的是一個項目由很多部分組成。這通常用類內部的數組/列表/集合等表示,而不是繼承結構。

Many to Many(M:M): 這種與現有技術的關係是不可能的。出於這個原因,我們需要將它與一個「關聯」表加入到兩個一對多的關係中。兩個一對多關係的許多方面總是在關聯/鏈接表上。

對於你的例子,說你需要多對多的人是正確的。因爲對於許多關係來說,兩對多實際上是一個多(意味着多於一個)。這是你讓系統工作的唯一方法。除非你打算研究relational calculus的領域來找到一些可以實現這一點的新型關係。

對於這樣的關係(m2m),您有兩種選擇,要麼在鏈接器表中創建一個複合鍵,以便字段組合成爲唯一條目(如果您對數據庫優化感興趣,這是較慢的選擇,但需要更小的空間)。或者,您使用自動生成的id列創建第三個字段,並將其作爲主鍵(對於db優化,這是更快的選擇,但佔用更多空間)。

在上面具體的例子...

一個真實世界的例子是電話號碼,用戶和公司。公司可以有許多電話號碼,用戶可以有許多電話號碼,但理想情況下,用戶不應該提供與公司相同的電話號碼,因爲在數據庫中會有重複的內容。

這與電話號碼錶格作爲公司和用戶之間的鏈接表是多對多的關係。如上所述,爲確保不重複電話號碼,只需將其設置爲主鍵或使用其他主鍵並將電話號碼字段設置爲唯一。

對於這樣的問題,這實際上取決於你如何說出它們。是什麼讓你對此感到困惑,以及你如何克服這種困惑才能看到解決方案很簡單。如下改述問題。首先要問的是一對一,如果答案是否定的,繼續前進。接下來要問的是,這是一對多的問題,如果答案是沒有進展的話。剩下的唯一選擇是多對多。但要小心,確保在繼續之前仔細考慮前2個問題。許多缺乏經驗的數據庫人員通常將複雜的問題定義爲多人對多人。到目前爲止,最流行的關係類型是一對多(我會說90%),其中多對多和一對一分別將剩下的10%7/3分開。但這些數字只是我個人的觀點,所以不要把它們作爲行業標準的統計數據。我的觀點是要做更多的事情,在選擇多對多之前絕對不是一對一的。這是值得額外的努力。

因此,現在要找到兩者之間的鏈接器表,決定哪兩個是您的主表以及哪些字段需要在它們之間共享。在這種情況下,公司和用戶表都需要共享手機。 Hense你需要製作一個新的手機表作爲鏈接器。

當你決定沒有3個人爲你工作時,誤會的警告報警應該顯示。這應該足以告訴你,你根本就沒有正確表達關係問題。隨着時間的推移,你會變得更好,但這是一項必不可少的技能,真正應該儘快掌握自己的技能。

當然,你也可以去一個面向對象的數據庫,這將允許一系列其他關係稱爲「分層」關係。如果你也想成爲一名程序員,那太好了。但我不會推薦這個,因爲當你開始尋找結合各種關係類型的方法時,它會讓你的頭部受傷。特別是考慮到沒有太大需求,因爲世界上幾乎所有的數據庫都只由這三種類型的關係組成,除非它們是超級特殊的。

希望這是一個合理的答案。感謝您花時間閱讀它。

0

對於您的電話號碼示例,您可以將電話號碼自行放入表格中,並帶有ID。

然後您鏈接到每個用戶和公司的phone_id。

對於您父母的例子,您不要將孩子鏈接到父母 - 而是將父母鏈接到孩子。或者,你把父母都放在同一張桌子上,孩子只和他們中的一個聯繫。

1

只需將電話號碼作爲聯繫人號碼錶中的鍵。

+0

不適用於用戶或公司可以有多個電話號碼。 – sqwk

+1

@sqwk,爲什麼不呢?只要公司沒有兩個*相同的電話號碼,它就應該可以工作。你爲什麼要記錄兩次相同的電話號碼? – sqlvogel