1

有人建議我在項目中使用一張表格,雖然我不能說爲什麼,但我認爲這不是一個好主意。FK專欄指向各種表格

MyTable的(MyTableId PK,類型INT NOT NULL,MyForeignKey INT NOT NULL)

MyForeignKey可以指向取決於類型的值的各種表中的數據。當然,我們不能使用這樣的模型來強制FK的完整性,但是這種說法足以不使用它嗎?

我給你舉個例子,說明它可以用在哪裏。假設系統中有一個Notes表,用於保存有關各種對象的Notes;有關用戶注意事項,有關文件等通常情況下,我想這個模型化像這樣:

筆記(NoteId PK,文字VARCHAR(4000),用戶ID INT NULL,DocumentId INT NULL,...)

什麼我的同事提議是有,而不是這樣一個表:

筆記(NoteId PK,文字VARCHAR(4000),對象類型,的ObjectId)

有了第二個執行,對象類型會告訴我們的ObjectId是否指向一個排在Users表或Documents表中。它的優點是,如果我們想添加另一種類型的對象,則數據庫結構和代碼需要更少的修改。

每個解決方案的優缺點是什麼?

注意:我們永遠不會有無數的對象類型。它應該保持在10以下。

實際上,我們現實生活中的情景有點複雜。它與用戶可能或不可以訪問各種類型的對象(文檔,筆記,事件等)的權限系統有關。

因此,現在在我的數據庫模型中,我有這些對象的表,使用它們和用戶之間的關係的附加表(UserDocuments,UserNotes,UserEvents等)權限通過這些鏈接表中的屬性設置。

我的同事提議有一個單獨的權限表而不是像這樣

權限(PermissionId PK,用戶ID INT,對象類型,的ObjectId,......等權限字段...)

這是一個好主意?

此外,我們可以稱之爲EAV或Open Schema嗎?這與我在這些主題上閱讀的完全不一樣。

回答

0

那麼,在我的老實說,bot解決方案是正確的,但爲了不同的目的。正如你所提到的這類計數的數量,這通常是推動決策的唯一因素。

我假設我們正在談論OLTP系統。所以,如果類型的數量相對較少,並且您確定它不會改變(尤其是不會長大),您應該爲具有不同類型的單獨列選擇解決方案。

如果類型的數量很大(在我看來10是一個很大的數字),你應該選擇類型和鍵列的解決方案。

一般來說,多列變體更好,因爲您可以使用DBMS機制來保持數據的完整性,在選擇類型/鍵列變體時您必須自行開發這些機制(即觸發器和過程)。有時候最好選擇類型/關鍵字列變體,因爲開發和維護工作不像結構變化那麼大 - 如果您在生產中使用系統期間沒有發現添加或刪除FK列的任何問題,仍然可以選擇多列變體(在這種情況下它只是一個存儲成本)。

2

這是一個壞主意。當您在同一列中混合多種類型的數據並添加相鄰類型列以消除歧義時,您幾乎總是會後悔後果。

如果你正確地加入,你的加入條件將變得更加複雜,並且你的加入將會運行得更慢。如果你不正確地加入,你會得到錯誤。忘記檢查類型列是錯誤的常見來源。

最好是將指針指向不同列中的不同表。但是,可能會有一個非常不同的設計,甚至會更好。

您收集的多種類型的對象似乎很適合稱爲「類表層次結構」的設計技術。這種技術基本上爲類和子類使用單獨的表,並使用共享的主鍵。共享主鍵需要您的應用程序中的代碼將主鍵從類表傳播到子類表。但是這是值得的。

單獨的類型列是不必要的,因爲類表和子類表之間的聯接會自動刪除與不同類相關的行。它光滑,簡單和快速。

如果您要查找SO中子類的類表繼承或關係建模的示例,您將獲得許多信息豐富的Q & As。


編輯將「類表層次結構」更改爲「類表繼承」。

+0

我並沒有完全理解你表達的類表層次結構的含義。我在這裏和谷歌上對這個主題進行了一些研究,但是沒有發現任何確鑿的結論......也許是因爲單詞,表格和層次結構過於籠統...... –

+0

你的困惑是我的錯。而不是「Class Table Hierarchy」,我應該說「Class Table Inheritance」。我編輯了我的回覆以反映這一點。我還編輯了你的OP來包含相應的標籤。按照相關示例的標籤。 –