1

データベース スキーマを計画していますが、最善の方法がわからない状況に遭遇しました。私が提案した各ソリューションの長所と短所のリストを実際に探しています。おそらくデータベースのベスト プラクティスに適合する推奨事項が続きます。

したがって、問題は、それらの間に複数の多対多の関係を持つ 2 つのエンティティがあることです。2 つのテーブルは Teams と People です。チームは多くの人で構成され、個人はチームで 1 つまたは複数の役割を持つことができます。役割には、チーム リーダー、チーム メンバー、チーム フォロワーなどがあります。ある人は、特定のチームに対して複数の役割を持つ場合がありますが、理想的には、これらの役割のサブセットは相互に排他的であり、残りは排他的ではありません。

私が検討した解決策は次のとおりです。

1) ロールごとに個別のジャンクション テーブルを作成します。各テーブルの行の存在は、1 人の人物が 1 つのチームに属していることを意味し、特定のテーブルはチームでのその人物の役割を示します。相互に排他的なロールは、アプリケーション レベルで適用する必要があります。

2) 単一のジャンクション テーブルを作成し、そのテーブルに列挙を格納して、個人が持つロールを指定します。特定の人物とチームの組み合わせには、このテーブルに複数の行が含まれる場合があり、その人物がチームで持つ役割ごとに 1 つずつです。特定のロールの相互排他性は、アプリケーション レベルで実施する必要があります。

3) 単一のジャンクション テーブルを作成し、ロールごとに 1 つずつ、ブール フラグのリストをテーブルに保存します。個人とチームの組み合わせごとにテーブルに 1 つの行があり、フラグによってそのチームでのユーザーの役割が決まります。相互に排他的なすべてのロールがテーブルの 1 つの列挙型フィールドを共有できるため、データベース レベルで相互排他性を適用できます。

4) 2 つのジャンクション テーブルを作成します。これは、(2) と (1) を組み合わせたようなもので、相互排他性をデータベース レベルで強制することができます。相互に排他的なロールの列挙を持つ 1 つのジャンクション テーブルがあり、他の (列挙を持つ) ジャンクション テーブルはすべての非排他的なロールを処理します。

私が忘れているものはありますか?最も自然に見える選択肢はどれですか?

ありがとう

4

2 に答える 2

1

People と Team の各テーブルはエンティティを表します。交差テーブルまたはジャンクション テーブルはそれぞれ、エンティティ間の関係を表します。複数の可能なリレーションシップがある場合、複数のジャンクション テーブルを持つことは理にかなっています。

一部の関係は相互に排他的である可能性があることを示唆しています。それは修正するのに十分簡単な問題です。

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' )
);

これにより、Captain と Member の両方の関係が定義されます。Person <-> Team エントリは 1 つだけ作成でき、'C' または 'M' のいずれかで指定する必要があります。したがって、人はチーム キャプテンまたはチーム メンバーになることができますが、両方になることはできません。

2 つのリレーションシップに対して 1 つのジャンクション テーブルを使用できるという利点もあります。

つまり、関係タプルに追加したい船長のみおよびメンバーのみのデータがない限りです。次に、2 つの「サブジャンクション」テーブルを追加できます。ここにそれらは説明用です。

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 のエントリが特定の人物を特定のチームのキャプテンとして定義している場合、その人物とそのチームの組み合わせをメンバー テーブルに挿入することはできません。Captains テーブルにのみ存在できます。およびその逆。

于 2015-05-10T05:30:04.903 に答える