0

我正在計劃一個數據庫模式,並且遇到了一種我不知道繼續進行的最佳方式的情況。我真的在尋找我提出的每個解決方案的優缺點清單,可能後面會有一個符合最佳數據庫實踐的建議。相同實體之間的多個連接表

所以,問題是我有兩個實體多個他們之間的多對多關係。兩張桌子是團隊和人民;團隊由很多人組成,一個人可以在團隊中擔任一個或多個角色。角色包括團隊領導者,團隊成員,團隊追隨者等。一個人可能對特定團隊有多個角色,但理想情況下,這些角色的子集是互斥的,而其餘的則不是。

這裏是我考慮的解決方案:

1)爲每個角色創建一個單獨的結表。每個表格中存在一行表示一個人屬於一個團隊,並且該特定表格指示該人員在團隊中的角色。相互排斥的角色必須在應用程序級別執行。

2)創建一個單一的聯結表並在該表上存儲一個枚舉來指定一個人擁有哪個角色。一個給定的人員組合可能在此表中有多行,每個角色與該組在該團隊中的角色有關。必須在應用程序級別執行某些角色的相互排斥。

3)創建一個單結表,並在表中存儲布爾標誌列表,每個角色一個布爾標誌。每個人員組合在表格中都有一行,標記決定了用戶在該組中的角色。相互排斥可以在數據庫級別執行,因爲所有互斥的角色可以在表上共享一個枚舉字段。

4)創建兩個聯結表。這是(2)和(1)的組合,允許在數據庫級別執行相互排他性。將有一個聯合表具有用於互斥角色的枚舉,而另一個聯結表(用枚舉)將處理所有非獨佔角色。

有什麼我忘記了嗎?哪個選項似乎最自然?

謝謝

回答

0

你已經偶然發現了黨的模型! :)

只是將個人和組織存儲在一張表中。這被稱爲單表繼承。如果你使用像PG那樣的db,那麼空值不會佔用任何空間。

與角色相同。將它們存放在一張桌子中,除非它變得笨重。

如果您使用像hibernate這樣的ORM來更新您的數據庫模式,它可以非常容易地切換到類表繼承。我認爲STI在開發過程中更容易處理。

0

每個表人員和團隊代表實體。交叉表或交叉表每個表示實體之間的關係。如果你有多個可能的關係,那麼有多個聯結表是有意義的。

您提示某些關係可能是相互排斥的。這是一個足夠簡單的問題來解決。

create table CaptainOrMember(
    PersonID int not null, 
    TeamID int not null, 
    C_or_M char(1) not null, 
    constraint PK_CaptainOrMember primary key(PersonID, TeamID), 
    constraint FK_CaptainOrMember_Person foreign key(PersonID) 
     references People(ID), 
    constraint FK_CaptainOrMember_Team foreign key(TeamID) 
     references Team(ID), 
    constraint CK_CaptainOrMember_OneOrOther check(C_or_M in('C', 'M') 
); 

這定義了船長和成員關係。只有一個人< - >可以進入隊伍,並且必須用'C'或'M'指定。所以一個人可以成爲一名隊長或一名隊員,但不能同時兼任。

它具有爲兩個關係使用一個聯結表的附加優勢。

也就是說,除非您有一些Captain-only和僅限會員的數據要添加到關係元組中。然後你可以添加兩個「子結」表。這裏他們是爲了說明。

alter table CaptainOrMember add constraint UQ_CaptainOrMember_OneOrOther unique(PersonID, TeamID, C_or_M); 

create table Captains(
    PersonID int not null, 
    TeamID int not null, 
    C_or_M char(1) not null, 
    ..., 
    ..., <Captain related data> 
    ..., 
    constraint PK_Captains primary key(PersonID, TeamID), 
    constraint CK_Captains_OneOrOther check(C_or_M = 'C'), 
    constraint FK_Captains_Captain foreign key(PersonID, TeamID, C_or_M) 
     references CaptainOrMember(PersonID, TeamID, C_or_M) 
); 

create table Members(
    PersonID int not null, 
    TeamID int not null, 
    C_or_M char(1) not null, 
    ..., 
    ..., <Member related data> 
    ..., 
    constraint PK_Members primary key(PersonID, TeamID), 
    constraint CK_Members_OneOrOther check(C_or_M = 'M'), 
    constraint FK_Members_Member foreign key(PersonID, TeamID, C_or_M) 
     references CaptainOrMember(PersonID, TeamID, C_or_M) 
); 

如果表CaptainOrMember的條目定義一個特定的人作爲一個特殊團隊的隊長,那麼該組合那個人和團隊不能插入成員表。它只能存在於船長表中。反之亦然。

相關問題