データベース設計の初心者として、私は多対多の関係の実践について質問があります。
この質問は、実際にはこの question のフォローアップ質問ですが、コメントで説明するには大きすぎます。
デザインは次のようにする必要があります(下の画像):
person
は複数のphone numbers
を持つことができますclub
は複数のphone numbers
を持つことができますphone number
は1 club
または1 person
のいずれかにのみ属することができます私の理解では、これはmany to many
の関係ではなく、many to one
です。
ただし、phone number
は他の2つのテーブルに属することができます。
では、電話番号に2列追加する必要がありますか? 1はFKでperson
に、1はFKでclub
に?電話番号が入力されたときにそれらの1つをnull
のままにしますか?
個人的には、追加のテーブルcontact
を使用して、このテーブルにperson
およびclub
リンクを設定してから、このテーブルにphone numbers
リンクを設定する方が良いと思いましたまた。
しかし、...
電子メールアドレスに関しても同じ状況です。したがって、私の考えは、それらを同じcontact
テーブルにもリンクすることでした。これは良いステップでしたか、それともclub - email
とperson - email
の関係について別のテーブルを追加する必要がありましたか?
実際のフォローアップを考えると、私の質問が少し明確であることを願っています。
-edit-
私の意図は、スキーマが正しくないようです。
あなたの仕様が少し複雑になっていることに気づきました(意図的に正しいですか?)。この種のシナリオはrelational設計の視野を広げるのに役立つので、これは有益な事実だと思います。
そのような状況に関して、私はあなたにこれらの新しい条件に対処するための2つの同様の方法を提案するつもりです。最初の例では(super)type-subtype clusterの使用を提案し、2番目の例では2つのone-to-many relationshipを推奨します。このように、エンティティPerson
(またはClub
)とTelephoneNumber
の間、およびPerson
(またはClub
)とEmailAddress
の間で指定する関係に対処します。
個々の質問のコンテキスト内で私の提案を説明しますが、その前に、まずシナリオを理解する方法を知っておく必要があります。次のように理解します。
Telephone
とEmail
はどちらもContactMeans
のタイプです。ContactMeans
(またはPerson
)のparticular型のClub
は修正する必要があります。ContactMeans
(またはPerson
)の特定のタイプのClub
が修正されると、このPerson
(またはClub
)は、このようなタイプのContactMeans
のone-to-manyオカレンスを通じて到達できます。これらのオカレンスのeach oneがTelephone
またはEmail
の同じタイプに属していることを確認します。個人的には、追加のテーブル
contact
を使用し、このテーブルにperson
およびclub
リンクを設定してから、このテーブルにも_phone numbers
_リンクを設定する方が良いと思いました。だが、...
メールアドレスに関しても同じ状況です。したがって、私の考えは、それらを同じ
contact
テーブルにもリンクすることでした。これは良いステップでしたか、または_club - email
_と_person - e mail
_の間の関係について別のテーブルを追加する必要がありましたか?
はい、別のテーブルを追加することは良いステップであり、私にとっては最良の方法ですが、いくつかの改良が必要です。ここで私の最初の提案が始まります。あなたは2つのスーパータイプサブタイプクラスターを利用する必要があります。
firstの場合、Party
と呼ばれるテーブルを含めます(これは他の回答で述べられています)。このテーブルは、特定のClub
またはPerson
(Party
サブタイプ)を特定のContactMeans
、Telephone
またはEmail
に関連付ける目的を果たします。
特定のParty
が1種類の連絡手段でのみ修正されるという事実を保存する必要があるため、ContactMeansType
という名前のPRIMARY KEYを持つContactMeansTypeCode
というテーブルを含めることをお勧めします。次に、Party
テーブルで、_ContactMeansType.ContactMeansTypeCode
_を指すFOREIGN KEYを追加する必要があります。
それからsecond supertype-subtypeクラスターが登場します。この場合、Contact
テーブルを "ContactMeans
"(Telephone
とEmail
のスーパータイプ)と呼び、PartyId
(FOREIGN KEYが_Party.PartyId
_)とContactMeansNumber
を参照する2つの列で構成される主キーを保持します。すべてのContactMeans
は型を保持する必要があるため、_ContactMeansType.ContactMeansTypeCode
_を指すContactMeansTypeCode
という名前のFOREIGN KEYを追加します。
次に、Party
(Club
またはPerson
)の特定のオカレンスが、そのようなオカレンスに対して修正されているContactMeansType
(Telephone
またはEmail
)を介してのみ到達できることを保証するために、検証メソッドを確立する必要があります。この取り組みには、列_Party.ContactMeansTypeCode
_および_ContactMeans.ContactMeansTypeCode
_を使用します。例えば:
Party
がTelephone
によってのみ到達するように修正されていると仮定し、新しいContactMeans
を挿入しようとする場合、この_ContactMeans.ContactMeansTypeCode
_に含まれる値が値と同じであることを確認する必要があります。 _Party.ContactMeansTypeCode
_に含まれている場合は、INSERTを続行します。そうでない場合は、前述のINSERTの試行を拒否します。 MySQLを使用しているため、MySQLリファレンスマニュアルの トリガーに関するコンテンツ がこの目的に関連している可能性があります。このメソッドの論理構造を示すIDEF1Xデータモデルを示す図1を参照してください。
*見落とさないでくださいリレーショナルキーは、ビジネスルールの大部分を形成するために使用されているため、その強力な機能を提供します。
この意味で、たとえば、それは注目に値しますPartyId
と呼ばれるPRIMARY KEYがmigratedをParty
からContactMeans
に、次にContactMeans
からTelephone
またはEmail
にどのように持つか。上記のプライマリキーは、Party
からClub
またはPerson
(それぞれrolenamesClubId
およびPersonId
を受け取る)に移行し、次にClubMember
(PersonId
がMemberId
としてロールネームされている)に移行しました。これにより、テーブルのこの「チェーン」すべてに参照整合性が提供されます。
この外部。PDF形式のドキュメントでは、この方法をより詳細に扱います。
私が理解しているように、これは_
many to many
_関係ではなく、_many to one
_です。ただし、_
phone number
_は他の2つのテーブルに属することができます。それでは、電話番号に2列追加する必要がありますか? 1はFKでperson
に、1はFKでclub
に?電話番号が入力されたときにnull
の1つを残しますか?
はい、提示したビジネスルールに従って、この状況は多対1(または1対多)relationshipで処理できます。
そして、はい、与えられたTelephone
は、Person
またはClub
に属することができます。しかし、いいえ、Telephone
とPerson
を参照する2つのFOREIGN KEYSのClub
テーブルへの追加はお勧めしません。また、私の個人的な経験によれば、これはモデリング段階の兆候かもしれないため、それらをNULL
のままにすることはお勧めしません。拡張する必要があります。
上記の代わりに、2番目の方法を提案します。この場合も、Party
というスーパータイプテーブルを使用します。このテーブルは、Club
またはPerson
とTelephone
またはEmail
を「リンク」します。
指定されたParty
が特定の種類の連絡手段で修正されているという事実を表す列を追加する必要があるため、PRIMARY KEY(_Party.ContactMeansCode
_になる列_ContactMeans.ContactMeansCode
_を追加します)ContactMeans
という名前のテーブルの。または、_Party.IsFixedWithEmail
_または_Party.IsFixedWithTelephone
_というBOOLEAN列を使用してこの値を処理することもできます。
図2に示されているように、このオプションでは、Telephone
とEmail
はmany-to-oneとParty
の関係で構成され、次に後者からClub
またはPerson
に。
IsPrimary
からTelephone
およびEmail
までの列を含めました。これは、個々のTelephone
(またはEmail
)が特定のParty
に接続するための(対応する型の)メインインスタンスとして確立されているという事実を格納するのに役立ちます。この側面については、プライマリとして設定できるインスタンスが1つだけになるようにメソッドを作成する必要があります。
次に、Party
(Club
またはPerson
)の特定のインスタンスが、そのようなインスタンスに対して修正されているContactMeans
(Telephone
またはEmail
)を通じてのみ(または経由して)到達できることを検証する手順を定義する必要があります。列_Party.ContactMeansCode
_は、この目標を達成するのに役立ちます。例えば:
Party
がEmail
を介してのみ(_Party.ContactMeansCode
_列の特定の値によって)連絡されるように修正されているため、そのようなEmails
の新しいParty
のINSERTのみを受け入れる必要があり、もちろんすべてを拒否するこのTelephone
のParty
テーブルでのINSERT試行。ここでも、MySQLを使用しているため、TRIGGERSを使用する必要がある場合があります。この手順の論理構造を示すIDEF1Xデータモデルを図2で参照してください。
同じ外部。PDF形式のドキュメントこの2番目の方法にも、より詳細な扱いをします。