5

問題のビジュアル

「CommonChild」エンティティがサブタイプ A または B のいずれかの子になることができるが、C ではないという上記の問題を考えてみましょう。リレーショナル [SQL] データベースで物理モデルを設計するにはどうすればよいでしょうか?

理想的には、ソリューションは...

  1. CommonChild とそれに関連するサブタイプとの間の識別関係。
  2. 1:N の関係。

可能な解決策

  1. サブタイプをスーパータイプに追加し、サブタイプ A と B を新しいサブタイプの下に移動します。CommonChild は、新しく作成されたサブタイプに対して FK 制約を持つことができます。上記の場合は機能しますが、サブタイプ A および C との関係を持つことができるが B とは関係を持たない追加のエンティティが追加された場合は機能しません。

  2. CommonChild と SuperType の間に FK 制約を追加します。新しいタプルを CommonChild に許可する前に、スーパータイプの識別子に対してトリガーまたはチェック制約 (UDF を使用) を使用します。単純なように見えますが、CommonChild はほとんど新しいサブタイプそのもののように見えます (そうではありません)。

  3. 私のモデルには根本的な欠陥があります。改造すれば問題はなくなるはずです。

他の可能な解決策、または既に提案した上記の解決策のいずれかの確認を探しています。

ありがとう!


編集

Branko Dimitrijevic が提供する専用の外部キー ソリューションを実装します (受け入れられた回答を参照)。

この場合、次のように少し変更します。

  1. スーパータイプ、サブタイプ、および「CommonChild」はすべて同じ PK を持ちます。
  2. PK は 3 列のコンポジットです。

変更は、サブタイプと "CommonChild" (Dimitrijevic によって提供された正確なモデルから "CommonChild" の属性を差し引いたもの) の間で排他的 FK 制約を適用することだけが役割を持つ中間テーブルを作成することです。CommonChild の PK には、中間テーブルに対する通常の FK 制約があります。

これにより、"CommonChild" が 2 セットの 3 列の複合 FK を持つことができなくなります。さらに、識別関係はスーパータイプから「CommonChild」まで維持されるため、[読み取り] クエリは中間テーブルを完全に無視できます。

4

2 に答える 2

3

排他的な外部キーのバリエーションが必要なようです:

CREATE TABLE CommonChild (
    Id AS COALESCE(SubTypeAId, SubTypeBId) PERSISTED PRIMARY KEY,
    SubTypeAId int REFERENCES SubTypeA (SuperId),
    SubTypeBId int REFERENCES SubTypeB (SuperId),
    Attr6 varchar,
    CHECK (
        (SubTypeAId IS NOT NULL AND SubTypeBId IS NULL)
        OR (SubTypeAId IS NULL AND SubTypeBId IS NOT NULL)
    )
);

ここで注意すべき点がいくつかあります。

  • NULL 可能なFOREIGN KEYが 2 つあります。
  • これらの FK の1 つだけを非 NULL にすることを許可する CHECK があります。
  • IdPRIMARY KEYでもあるFKの1つ(現在NULLでない方)に等しい計算列があります。これにより、次のことが保証されます。
    • 1 つの親が複数の子を持つことはできません。
    • 「孫」テーブルはCommonChild.Id、その FK から直接参照できます。はSuperType.Id効果的にずっと下に移入されます。
    • MS SQL Server で問題となる NULL 許容の UNIQUE 制約をいじる必要はありません (以下を参照)。

同様のことを行うDBMSに依存しない方法は...

CREATE TABLE CommonChild (
    Id int PRIMARY KEY,
    SubTypeAId int UNIQUE REFERENCES SubTypeA (SuperId),
    SubTypeBId int UNIQUE REFERENCES SubTypeB (SuperId),
    Attr6 varchar,
    CHECK (
        (SubTypeAId IS NOT NULL AND SubTypeAId = Id AND SubTypeBId IS NULL)
        OR (SubTypeAId IS NULL AND SubTypeBId IS NOT NULL AND SubTypeBId = Id)
    )
)

残念ながら、複数の NULL を含む UNIQUE 列は、MS SQL Server では許可されていません。これは、ほとんどの DBMS では当てはまりません。SubTypeAIdただし、直接参照したくない場合は、 UNIQUE 制約を省略できますSubTypeBId

于 2013-08-18T08:44:34.783 に答える
3

ここで何が足りないのだろうか?

確かに、具体的な問題の文言がなければ難しいですが、物事は少し逆さまに感じます.


ここに画像の説明を入力

于 2013-08-18T18:23:38.233 に答える