web-dev-qa-db-ja.com

これは多対多の受け入れ可能な方法ですか?

データベース設計の初心者として、私は多対多の関係の実践について質問があります。

この質問は、実際にはこの 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 - emailperson - emailの関係について別のテーブルを追加する必要がありましたか?

実際のフォローアップを考えると、私の質問が少し明確であることを願っています。

-edit-
私の意図は、スキーマが正しくないようです。

  • 人/クラブは連絡先を1つだけ持つことができます
  • 連絡先は1人の人物/クラブにしか所属できません
  • 電話番号は1つの連絡先にのみ属することができます
  • メールアドレスは1つの連絡先にのみ属することができます
  • 連絡先は複数の電話番号を持つことができます
  • 連絡先は複数のメールアドレスを持つことができます

Schema

3
Vahx

あなたの仕様が少し複雑になっていることに気づきました(意図的に正しいですか?)。この種のシナリオはrelational設計の視野を広げるのに役立つので、これは有益な事実だと思います。

そのような状況に関して、私はあなたにこれらの新しい条件に対処するための2つの同様の方法を提案するつもりです。最初の例では(super)type-subtype clusterの使用を提案し、2番目の例では2つのone-to-many relationshipを推奨します。このように、エンティティPerson(またはClub)とTelephoneNumberの間、およびPerson(またはClub)とEmailAddressの間で指定する関係に対処します。

あなたのビジネスルールの私の理解

個々の質問のコンテキスト内で私の提案を説明しますが、その前に、まずシナリオを理解する方法を知っておく必要があります。次のように理解します。

  • TelephoneEmailはどちらもContactMeansのタイプです。
  • ContactMeans(またはPerson)のparticular型のClubは修正する必要があります。
  • ContactMeans(またはPerson)の特定のタイプのClubが修正されると、このPerson(またはClub)は、このようなタイプのContactMeansone-to-manyオカレンスを通じて到達できます。これらのオカレンスのeach oneTelephoneまたはEmailの同じタイプに属していることを確認します。

提案された方法と個々の質問への回答

最初の方法

個人的には、追加のテーブルcontactを使用し、このテーブルにpersonおよびclubリンクを設定してから、このテーブルにも_phone numbers_リンクを設定する方が良いと思いました。

だが、...

メールアドレスに関しても同じ状況です。したがって、私の考えは、それらを同じcontactテーブルにもリンクすることでした。これは良いステップでしたか、または_club - email_と_person - e mail_の間の関係について別のテーブルを追加する必要がありましたか?

はい、別のテーブルを追加することは良いステップであり、私にとっては最良の方法ですが、いくつかの改良が必要です。ここで私の最初の提案が始まります。あなたは2つのスーパータイプサブタイプクラスターを利用する必要があります。

firstの場合、Partyと呼ばれるテーブルを含めます(これは他の回答で述べられています)。このテーブルは、特定のClubまたはPersonPartyサブタイプ)を特定のContactMeansTelephoneまたはEmailに関連付ける目的を果たします。

特定のPartyが1種類の連絡手段でのみ修正されるという事実を保存する必要があるため、ContactMeansTypeという名前のPRIMARY KEYを持つContactMeansTypeCodeというテーブルを含めることをお勧めします。次に、Partyテーブルで、_ContactMeansType.ContactMeansTypeCode_を指すFOREIGN KEYを追加する必要があります。

それからsecond supertype-subtypeクラスターが登場します。この場合、Contactテーブルを "ContactMeans"(TelephoneEmailのスーパータイプ)と呼び、PartyId(FOREIGN KEYが_Party.PartyId_)とContactMeansNumberを参照する2つの列で構成される主キーを保持します。すべてのContactMeansは型を保持する必要があるため、_ContactMeansType.ContactMeansTypeCode_を指すContactMeansTypeCodeという名前のFOREIGN KEYを追加します。

次に、PartyClubまたはPerson)の特定のオカレンスが、そのようなオカレンスに対して修正されているContactMeansTypeTelephoneまたはEmail)を介してのみ到達できることを保証するために、検証メソッドを確立する必要があります。この取り組みには、列_Party.ContactMeansTypeCode_および_ContactMeans.ContactMeansTypeCode_を使用します。例えば:

  • 特定のPartyTelephoneによってのみ到達するように修正されていると仮定し、新しいContactMeansを挿入しようとする場合、この_ContactMeans.ContactMeansTypeCode_に含まれる値が値と同じであることを確認する必要があります。 _Party.ContactMeansTypeCode_に含まれている場合は、INSERTを続行します。そうでない場合は、前述のINSERTの試行を拒否します。 MySQLを使用しているため、MySQLリファレンスマニュアルの トリガーに関するコンテンツ がこの目的に関連している可能性があります。

このメソッドの論理構造を示すIDEF1Xデータモデルを示す図1を参照してください。

Fig. 1. Clubs and Members DM - Contact Means First Method

*見落とさないでくださいリレーショナルキーは、ビジネスルールの大部分を形成するために使用されているため、その強力な機能を提供します。

この意味で、たとえば、それは注目に値しますPartyIdと呼ばれるPRIMARY KEYがmigratedPartyからContactMeansに、次にContactMeansからTelephoneまたはEmailにどのように持つか。上記のプライマリキーは、PartyからClubまたはPerson(それぞれrolenamesClubIdおよびPersonIdを受け取る)に移行し、次にClubMemberPersonIdMemberIdとしてロールネームされている)に移行しました。これにより、テーブルのこの「チェーン」すべてに参照整合性が提供されます。

この外部。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に属することができます。しかし、いいえ、TelephonePersonを参照する2つのFOREIGN KEYSのClubテーブルへの追加はお勧めしません。また、私の個人的な経験によれば、これはモデリング段階の兆候かもしれないため、それらをNULLのままにすることはお勧めしません。拡張する必要があります。

上記の代わりに、2番目の方法を提案します。この場合も、Partyというスーパータイプテーブルを使用します。このテーブルは、ClubまたはPersonTelephoneまたはEmailを「リンク」します。

指定されたPartyが特定の種類の連絡手段で修正されているという事実を表す列を追加する必要があるため、PRIMARY KEY(_Party.ContactMeansCode_になる列_ContactMeans.ContactMeansCode_を追加します)ContactMeansという名前のテーブルの。または、_Party.IsFixedWithEmail_または_Party.IsFixedWithTelephone_というBOOLEAN列を使用してこの値を処理することもできます。

図2に示されているように、このオプションでは、TelephoneEmailmany-to-onePartyの関係で構成され、次に後者からClubまたはPersonに。

IsPrimaryからTelephoneおよびEmailまでの列を含めました。これは、個々のTelephone(またはEmail)が特定のPartyに接続するための(対応する型の)メインインスタンスとして確立されているという事実を格納するのに役立ちます。この側面については、プライマリとして設定できるインスタンスが1つだけになるようにメソッドを作成する必要があります。

次に、PartyClubまたはPerson)の特定のインスタンスが、そのようなインスタンスに対して修正されているContactMeansTelephoneまたはEmail)を通じてのみ(または経由して)到達できることを検証する手順を定義する必要があります。列_Party.ContactMeansCode_は、この目標を達成するのに役立ちます。例えば:

  • 個々のPartyEmailを介してのみ(_Party.ContactMeansCode_列の特定の値によって)連絡されるように修正されているため、そのようなEmailsの新しいPartyのINSERTのみを受け入れる必要があり、もちろんすべてを拒否するこのTelephonePartyテーブルでのINSERT試行。ここでも、MySQLを使用しているため、TRIGGERSを使用する必要がある場合があります。

この手順の論理構造を示すIDEF1Xデータモデルを図2で参照してください。

Fig. 2. Clubs and Members DM - Contact Means Second Method

同じ外部。PDF形式のドキュメントこの2番目の方法にも、より詳細な扱いをします。

3
MDCCL