2013-11-23 59 views
1

比方說,我有產品(product)和類別(category)的表的表和它們之間存在通過補充表(product_category_xref)一個多一對多的關係。如何在多對多關係中建立一個鏈接?

有沒有一種方法,使一個,也是唯一一類「主」?

到目前爲止,我有兩個想法:

  1. 創建於product表,primary_category一個單獨的列,並將它包含的主要類別的關鍵。 我對此不喜歡的是數據冗餘(在primary_categoryproduct_category_xref中定義的同一類別)或類別匹配(驗證與primary_category和與product_category_xref.category相比)。

  2. 創建is_primary,在product_category_xref一個布爾列。 我不喜歡這個,可能有一種方法可以讓幾個類別爲主。

此外,許多一對多的關係,執行與外國的關鍵,但我不知道如何執行只是一個主要類別(或,也許,當一個類是由主,讓所有的完整性其他類別的相同產品非主要)。

這樣做的最好方法是什麼?

UPDATE:數據庫管理系統是在MySQL通過PHP接口mysqli的。

UPDATE2:這裏就是我終於實現了。 我在product_category_xref表中添加了一個不可爲空的整數列,priority。然後,主要類別primary是最大的。作爲一種有用的副作用,我也可以對類別進行排序。 我也用相反的方法添加了同樣的東西,以便在一個類別中對產品進行排序。 當然,這使得更新數據變得困難,但這並不經常發生。

+0

這裏見我的回答:** [在SQL中,爲它確定了兩個表來稱呼對方?](http://stackoverflow.com/questions/10446641/in-sql - 它可以爲兩個表參考到每個其他/ 10458105#10458105)** –

+0

哪個DBMS是這樣的? –

回答

0

形式爲product_primary_cat_xref的產品與產品具有1-> 1的關係並且與類別具有m-> 1的關係會爲您節省重複,並且不會以不必要的冗餘參照完整性。

+0

額外的表,是的。你建議的2個FK,不。在這個表中所有需要的是一個FK,引用'product_category_xref(product_id,category_id)'和'(product_id)'' –

3

我不同意ypercube,誰是在暗示這樣的設計將是有效的(無論DBMS)的

ERD

注意,在這個設計有額外的表引用您的多對一因爲它有產品和類別,但它的主要關鍵是只是產品。此設計強制執行以下兩項要求:

  • 主要產品類別是有效的產品類別組合。
  • 每種產品至多有一個主要產品類別。

此設計不能幫助您限制每個產品都必須具有主要產品類別,這隻能通過在Product表上添加強制外鍵列來實現。

但是,我不確定我會推薦這個解決方案到您的問題。雖然這個設計成功地強加了您所尋找的限制,但在您的代碼中使用它並不容易。您將不得不編寫代碼來處理產品類別的變化可能會影響您的主要產品類別的事實。該設計在持續狀態的數據上效果很好,但它對數據更改沒有好處。由於您需要一些程序邏輯來更改數據工作,因此您可能還會考慮更簡單的數據庫設計(例如,添加FK列Product.primary_category_id)並編寫程序邏輯以施加其他約束。這不是一種防止愚蠢的方法,只是一種不同的方式,可能更容易理解(因此保持)妥協。

哪一種方法取決於您對將多少約束儘可能多地納入模式的感覺有多強烈。

+0

'上的唯一約束。我同意表越多,訪問它們的代碼就越複雜。我的鏈接中的答案也表明了可能的不同方法(如標誌列和部分索引),它們可以在SQL-Server和Postgres中工作,而不需要額外的表。 –

+0

當然,這些強制要求「每個產品都必須有主要產品類別」。這可以在代碼中完成(按照您的建議),也可以在Postgres和Oracle中使用可選的FKs。 –

+0

@ypercube - 同意,根據DBMS可能會有更優雅的解決方案。 –

1

還有就是用第二種方法有某種考慮的解決方案:

它的基礎上爲空的唯一約束。

  • 擁有從產品表內 product_category_xref表額外的空能外鍵,稱爲primary_product_id
  • is_primary將可能爲空的數字列在 product_category_xref表的1長度,以及{1}可能值的CHECK 約束,即1值將顯示 is_primary爲真和空值示出了無 - 初級。
  • CHECK約束帶的值:對(primary_product_id + is_primary)
    (primary_product_id is null or ((primary_product_id = product_id) and (is_Primary is not null)))
  • UNIQUE約束。

SQLFIDLE sample (tested on oracle).

相關問題