2013-01-07 82 views
0

(我承認這很可能是重複的,但我不能找到基於搜索任何答案)一個表該隱連接兩個表

我有一些信息的表,可以在用戶加入,或在一家公司。有三種方法可以解決此問題:

  1. 爲表提供join_user_id列和join_company_id列,並且只填寫其中一個。
  2. 創建一個join_id列和一個joins_with_table列
  3. 複製主表,以便有兩個版本,一個只有一個join_user_id,另一個只有一個join_company_id。

我正在排除3因爲它不幹。我的問題是,哪些是真正的標準化設計(或者都不是)?

我該如何處理以下缺陷: 1.留下一堆容器,如果第三張桌子出現時不會優雅地增長,以及如何簡潔地加入? 2.我如何執行外鍵約束?我如何簡潔地加入?

回答

0

1或2都不是第三範式,因爲在一列中設置一個值可以告訴您有關另一列(不是主鍵)中的值的信息。這打破了完全依賴3NF所需主鍵的性質。

我一定會排除選項2,因爲創建外鍵將會非常棘手/不可能,並且可能會導致混淆列中值的含義。如果有人在不更改join_id列的情況下更改joins_with_table列,您可能不知道!

要在3NF中對此進行建模,您需要創建兩個新表,一個用於用戶,另一個用於公司。這些將有original_table_id, user_id(或公司),並以original_table_id作爲主鍵。然後,您需要驗證一個表中或另一個表中只有一個條目。

就我個人而言,我仍然會考慮在原始表格中添加這些額外的列,除非您認爲可能會添加更多的表格,您需要有條件地參考。你不應該設計避免空值,所以我不會擔心這一點。如果您需要在此表中返回有關公司和用戶的信息,則此解決方案和額外表格方法需要外部連接到usercompany表,因此查詢複雜性沒有實際差異。

0

不是說這是最好的做法,甚至它是否會工作在你的情況,但第四個選項可能是共同的列保持到usercompany表在一個單獨的表(也許user_comp_base)。然後,用戶和公司詳細信息可以使用與user_company_base表(其中可能還包含一個指示哪個表包含此行的詳細信息的列)中相同的密鑰進入單獨的user_detailscompany_details表。

然後你只需要在你的表中解決外鍵約束和簡潔連接問題的join_id_user_comp_base。當然這是以加入另一個表(user_detailscomp_details)的費用爲代價的,如果需要細節的話。

編輯:我認爲這個概念被稱爲表繼承。

+0

也看到http://stackoverflow.com/questions/13749525/relational-database-design-multiple-user-types/13752304#13752304 –

0

哪些是真正規範化的設計(或者它們都不是)?

所有這些都是「正常化」,但並非所有這些都同樣有用。

1)留下一堆容器,不會優雅地生長。

NULL由大多數DBMS相當有效地存儲。在理想情況下,通常是一個字節,或者甚至在一些DBMS上只有一個字節。

您可以使用CHECK來確保其中的一個是非NULL。

2)如何執行外鍵約束?

理論上,您可以將joins_with_table沿着FK遷移,然後在引用表中使用CHECK來確保正確的類型。很明顯,這很尷尬,浪費空間(除非DBMS支持計算/虛擬列)。

你可以依靠觸發器或(上帝保佑)應用程序邏輯,但聲明的約束應該是首選儘可能爲他們的簡單性,魯棒性和速度。

我立即排除了3,因爲它不幹。

不幸的是,關係數據庫通常不支持我們都從OO編程中熟悉的概念,因此可能會因此而遭受一些不必要的重複。例如,表格繼承(基表定義一個「結構」,兒童定義特定的FK)將是理想的緩解這種情況下的重複。

事實上,只要你不會讓比例失調,一些重複不是世界上最糟糕的事情。

如何簡潔地加入?

我不知道我理解你的問題 - 請澄清。根據您的需要,JOIN可以不僅受到桌面設計的影響,還受key design的影響。總而言之,除非您預計可能需要其他差異(3),否則我可能只想跟(1)一起去。