データベース設計:同じテーブルに対する2つの1対多の関係


20

私は、Chequing_Accountテーブル(予算、iban番号、およびアカウントの他の詳細を含む)を持っている状況をモデル化する必要があります。

言い換えれば、同じテーブルの2つの1対多の関係があります。

正規化の要件を尊重するこの問題の解決策を聞きたいです。私が聞いたほとんどのソリューションは次のとおりです。

1)PersonとCorporationの両方が属する共通エンティティを見つけ、これとChequing_Accountテーブルの間にリンクテーブルを作成します。これは私の場合は不可能であり、この特定のインスタンスではなく一般的な問題を解決したい場合でも可能です。

2)2つのエンティティをChequingアカウントに関連付ける2つのリンクテーブルPersonToChequingAccountとCorporationToChequingAccountを作成します。ただし、2人の人物が同じ当座預金口座を持つことは望ましくありません。また、自然人と法人が当座預金口座を共有することは望ましくありません。この画像をご覧ください

http://i41.tinypic.com/35i6kbk.png

3)法人および自然人を指す2つの外部キーをChequing Accountに作成しますが、個人と会社が多数の当座預金口座を持つことができるように強制しますが、ChequingAccount行ごとに両方の関係が指すことはないことを手動で確認する必要がありますchechquingアカウントは法人または自然人のいずれかであるため、法人および自然人。この画像をご覧ください

http://i40.tinypic.com/1rpv9z.png

この問題を解決する他の方法はありますか?


あなたは、例えば、Aのために持っていることについて考えたことOwnerTypeIDChecquingAccountして、テーブル1=Corporation2=NaturalPerson?そうすればOwnerIDChecquingAccountテーブルに1つだけが必要になりますOwnerTypeID
-RoKa

企業か自然人かを知る必要があるだけでなく、それぞれのIDを知る必要があるので、ID番号と1または2の値だけが必要です!ソリューション3はここで見つけたものです。企業または自然人のIDを持つ2つの列があります
-dendini

2
はい、解決策は有効なオプションです。ほとんどのDBMSでは、チェック制約を使用して2つのFKのうち1つだけが「アクティブ」であるように強制できますCHECK (CorporationID IS NOT NULL AND NaturalPersonID IS NULL OR CorporationID IS NULL AND NaturalPersonID IS NOT NULL)。それははるかに「きれい」です。
ypercubeᵀᴹ

はい、わかりますが、ChecquingAccountテーブルにOwnerTypeID=1andのレコードがありOwnerID=123、それがtype Corporationであり123CorporationテーブルのID であることを示しています。OwnerTypeIDはどのテーブルを示し、OwnerIDはそのテーブルのIDを示します。
-RoKa

1
オプション#1はどのように不可能ですか?「Corporation」という言葉は基本的に「合法的に人であるビジネス」を意味します。Customersテーブルと呼びます。
すべての取引のジョン

回答:


15

リレーショナルデータベースは、この状況を完全に処理するようには構築されていません。あなたにとって最も重要なものを決定し、トレードオフを行う必要があります。いくつかの目標があります:

  • 第3正規形を維持する
  • 参照整合性を維持する
  • 各アカウントが企業または自然人に属するという制約を維持します。
  • データを簡単かつ直接取得する機能を保持する

問題は、これらの目標のいくつかが互いに競合することです。

サブタイピングソリューション
企業と個人の両方を組み込むスーパータイプを作成するサブタイピングソリューションを選択できます。このスーパータイプは、おそらくサブタイプの自然キーとパーティション属性(例えばcustomer_type)の複合キーを持っているでしょう。これは、正規化が行われている限り問題ありません。参照整合性と、企業と個人が相互に排他的であるという制約を強制できます。問題はcustomer_type、アカウントをアカウント所有者に参加させるタイミングに基づいて常に分岐する必要があるため、データの取得が難しくなることです。これはおそらくUNION、クエリで多くの反復SQLを使用していることを意味します。

2つの外部キーソリューション
アカウントテーブルに2つの外部キーを保持するソリューションを選択できます。1つは企業用、もう1つは個人用です。このソリューションにより、参照整合性、正規化、相互排他性を維持することもできます。また、サブタイピングソリューションと同じデータ取得の欠点があります。実際、このソリューションはサブタイピングソリューションと似ていますが、結合ロジックを「早めに」分岐するという問題が発生する点が異なります。

それでも、多くのデータモデラーは、相互排他性の制約が適用されるため、このソリューションはサブタイピングソリューションよりも劣ると考えます。サブタイピングソリューションでは、キーを使用して相互排他性を強制します。2つの外部キーソリューションでは、CHECK制約を使用します。私は、チェック制約に対して不当なバイアスをかけている人々を知っています。これらの人々は、キーの制約を保持するソリューションを好むでしょう。

「非正規化」パーティショニング属性ソリューション
別のオプションとして、チェッキングアカウントテーブルに単一の外部キー列を保持し、別の列を使用して外部キー列の解釈方法を指定する方法があります(RoKaのOwnerTypeIDカラム)。これは、子テーブルへのパーティション属性を非正規化することにより、サブタイピングソリューションのスーパータイプテーブルを本質的に排除します。(パーティション属性は主キーの一部であるため、これは正式な定義による厳密な「非正規化」ではないことに注意してください)外部キー列の数を1つに減らします。このソリューションの問題は、検索ロジックの分岐を避けられず、さらに、宣言的な参照整合性を維持できないことです。SQLデータベースには、複数の親テーブルのいずれかに対応する単一の外部キー列を管理する機能がありません。

共有プライマリキードメインソリューション
この問題に時々対処する方法の1つは、IDの単一プールを使用して、特定のIDがサブタイプに属していても別のIDであっても混乱しないようにすることです。企業と自然人の両方に同じ銀行口座番号を発行することはないので、これはおそらく銀行のシナリオではかなり自然に機能するでしょう。これには、パーティショニング属性が不要になるという利点があります。スーパータイプのテーブルの有無にかかわらずこれを行うことができます。スーパータイプのテーブルを使用すると、宣言制約を使用して一意性を適用できます。それ以外の場合、これは手続き的に実施する必要があります。このソリューションは正規化されていますが、スーパータイプのテーブルを保持しない限り、宣言的な参照整合性を維持することはできません。複雑な検索ロジックを回避するために、まだ何もしません。

したがって、すべてのルールに従うクリーンなデザインを実現することは実際には不可能であると同時に、データ取得をシンプルに保つことができることがわかります。トレードオフがどこになるかを決める必要があります。


私のソリューション#2は、4つのグループのどれに属しますか?「非正規化パーティション属性のソリューションは、」かなり私にはクリアされていません...
dendini

@dendini-あなたのソリューション番号2は、私が概説したどのソリューションにも適合しません。これは、1つの法人に属するアカウントの要件に適合しないためです。中間テーブルの主キーを定義した方法は、多対多の交差点です。主キーがあった場合だけ corporation_idperson_id、あなたは、本質的にそのスーパータイプのテーブルを除くサブタイピングソリューションは、二つに分割されているだろうだろうと人々が複数のアカウントを保持することができませんでしたので、外部キーは、反転されています。この種の目的は無効です。
ジョエルブラウン

素晴らしい説明。@JoelBrown、クエリに関する「2つの外部キー」ソリューションのパフォーマンスへの影響は何ですか?また、2の代わりに6つ以上の外部キーが存在する可能性があることを考慮すると、このアプローチを引き続きお勧めしますか?
アマデオガヤルド

1
@AmadeoGallardo答えは「依存する」です。キーに対してクエリを実行することは、常にかなり効率的です。これは、一般に、少なくともシークではなくてもインデックススキャンを当てにすることができ、これらが迅速な操作であるためです。この問題は、2つの外部キーソリューションの両方のキーに対してクエリを実行したときに発生します。ここでは、クエリオプティマイザーに操作を実行するように依頼しています。せいぜい、これはクエリのコストを2倍にします。通常は、1つのキーに対してクエリを実行し、次に他のキーに対してクエリを実行し、結果をマージする必要があるため、通常は少し悪くなります。
ジョエルブラウン

@JoelBrown非正規化将来のSQLのバージョンは、2つの列に基づいて化合物の外部キーの定義を可能にすることによって、このアプローチを可能にすべきであるRefIDRefTable場所をRefTable固定IDことを識別するターゲット表です。このタイプのキーには多くのユースケースがあり、整合性を強化するために10個以上の関連付け/サブタイプテーブルを維持することが重要です。それらの場合、私はkey自分でこれを作成しました。
djmj
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.