2010-04-24 19 views
5

我必須添加功能到現有的應用程序,我遇到了一個數據情況,我不知道如何建模。我被限制在創建新的表格和代碼。如果我需要改變現有的結構,我認爲我的客戶可能會拒絕這個提議。儘管如果這是唯一的方法來解決這個問題,那我就不得不這樣做了。如何建模SQL Server中的互斥關係

我有一個項目表,我可以鏈接到任何數量的表,這些表可能會隨着時間的推移而增加。該項目只能鏈接到另一個表格,但另一個表格中的記錄可能有許多鏈接到它的項目。被連接的表/實體的

實例到是PersonVehicleBuildingOffice。這些都是獨立的表格。項目

實施例是PenStaplerCushionTyreA4 PaperPlastic BagPosterDecoration"

例如一個Poster可以被分配給一個或PersonOfficeBuilding。在未來,如果他們添加一個Conference Room表,它也可能被添加到該表中。

我intital的想法是:然後

Item 
{ 
    ID, 
    Name 
} 

LinkedItem 
{ 
    ItemID, 
    LinkedToTableName, 
    LinkedToID 
} 

LinkedToTableName場可以讓我找出正確的表在我的代碼鏈接到。

我對這個解決方案並不滿意,但我無法想到其他任何東西。請幫忙! :)

謝謝!

+0

如果你explaned更多關於你要存儲什麼類型的數據的一個位,爲什麼這將幫助;比如說,博客文章,人物或超市等物品?目標表代表什麼?我認爲你的抽象被打破了,但是爲什麼要說出來幾乎是不可能的,或者在不知道你想用它解決的問題的情況下提出一種不同的方法。 – 2010-04-24 13:59:41

+0

感謝羅蘭。我試圖添加到我的問題。請參閱編輯Q.如果仍然不夠詳細,我將再次編輯:) – littlechris 2010-04-24 14:10:17

回答

12

將表名稱存儲爲列值不是一種好的做法。這是一個糟糕的黑客攻擊。

有兩種標準的方式來做你想做的事情。第一個叫做單表繼承。這很容易被ORM工具所理解,但是它取消了一些標準化。這個想法是,所有這些實體 - Person,Vehicle,無論 - 都存儲在同一個表中,通常每個條目有幾個未使用的列,以及識別實體是什麼類型的鑑別器字段。

鑑別器字段通常是一個整型,它映射到代碼中的某個枚舉。它也可能是數據庫中某些查找表的外鍵,用於標識哪些數字對應於哪些類型(而不是表名稱,只是說明)。

另一種方法是多表繼承,這對您的數據庫更好,但不容易在代碼中映射。你可以通過一個基表來完成這個工作,它定義了所有對象的一些共同屬性 - 可能只是一個ID和一個名稱 - 所有的「特定」表(Person等)都使用基本ID作爲唯一的外鍵(通常也是主鍵)。

在第一種情況下,排他性是隱含的,因爲所有實體都在一個表中。在第二種情況下,關係在Item基礎實體ID之間,這也保證了唯一性。

請注意,對於多表繼承,您有一個不同的問題 - 您不能保證一個基本ID由一個繼承表使用。它可以被多個使用,或者根本不使用。這就是爲什麼多表繼承方案通常也有一個鑑別器列,以確定哪個表是「預期的」。同樣,這個鑑別器不包含表名,它擁有一個查找值,消費者可以(或不可以)使用它來確定要加入的其他表。

多表繼承與您當前的模式更接近匹配,所以我會建議使用該模式,除非您需要將此用於Linq to SQL或類似的ORM。

在這裏看到一個很好的詳細教程:Implementing Table Inheritance in SQL Server

0

你的鏈接表是好的。

您將遇到的麻煩是您需要在運行時生成動態sql。參數化的sql通常不允許FROM列表中的對象成爲參數。如果你想避免這種情況,你可以通過創建一個表來保存id(假設id在其他表中是唯一的)並且type_id表示哪個表是源,和生成的描述 - 例如來自inital記錄的名稱值。

當基本信息被修改時,您會觸發此非規範化列表的創建,您可以將其用於廣義查詢 - 然後在運行時需要時動態查詢。

9

找到共同車輛大廈辦公室東西。對於缺少更好的術語,我使用了實體。然後實現實體及其子類型之間的超類型/子類型關係。請注意,EntityID是所有子類型表中的PKFK。現在,您可以將項目錶鏈接到實體(所有者)。 在此模型中,一個項目可以只屬於一個實體;一個實體可以有(自己的)很多項目

model_mutually_exclusive_01

+1

您使用什麼軟件來生成該圖像? – goat 2010-04-25 05:10:40

+0

@chris,Visio 2007 – 2010-04-25 14:54:50