10

Bravo や Charlieに関連しているかもしれないし、関連していないかもしれない Alpha のものを持っているとしましょう。

これらは 1 対 1 の関係です。アルファは複数のブラボーに関連付けられません。また、ブラボーが複数のアルファに関連付けられることはありません。

私はいくつかの目標を持っています:

  • 習得と保守が容易なシステム。
  • データベース内で実施されるデータの整合性。
  • 私のデータの実世界の論理的な編成に一致するスキーマ。
  • 私のプログラミング内のクラス/オブジェクトは、データベース テーブルに適切にマップされます (Linq から SQL に似ています)
  • 高速な読み取りおよび書き込み操作
  • スペースの有効利用 (null フィールドが少ない)

3つのアイデアがあります...

PK = primary key  
FK = foreign key  
NU = nullable

多くの nullalbe フィールドを持つ 1 つのテーブル (フラット ファイル)…

      Alphas
      --------
   PK AlphaId
      AlphaOne
      AlphaTwo
      AlphaThree
   NU BravoOne
   NU BravoTwo
   NU BravoThree
   NU CharlieOne
   NU CharlieTwo
   NU CharlieThree

nullalbe フィールドがゼロの多くのテーブル…

      Alphas
      --------
   PK AlphaId
      AlphaOne
      AlphaTwo
      AlphaThree

      Bravos
      --------
FK PK AlphaId
      BravoOne
      BravoTwo
      BravoThree

      Charlies
      --------
FK PK AlphaId
      CharlieOne
      CharlieTwo
      CharlieThree

両方の最良(または最悪):多くのテーブルへのnullalbe外部キーがたくさん…

      Alphas
      --------
   PK AlphaId
      AlphaOne
      AlphaTwo
      AlphaThree
NU FK BravoId
NU FK CharlieId

      Bravos
      --------
   PK BravoId
      BravoOne
      BravoTwo
      BravoThree

      Charlies
      --------
   PK CharlieId
      CharlieOne
      CharlieTwo
      CharlieThree

アルファがブラボーまたはチャーリーのいずれかである必要があり、両方ではない場合はどうなりますか?

ブラボーとチャーリーだけでなく、アルファがデルタ、エコー、フォックストロット、ゴルフなどのいずれかになるとしたら…?


編集:これは質問の一部です:私のナビゲーションに最適なデータベース スキーマはどれですか?

4

9 に答える 9

8

各アルファを1つのブラボーだけに関連付けたい場合は、FK/PKを組み合わせて使用​​する可能性に投票します。

      Bravos
      --------
FK PK AlphaId
      BravoOne
      BravoTwo
      BravoThree

このようにして、唯一のブラボーがあなたのアルファを参照することができます。

BravosとCharliesが相互に排他的である必要がある場合、最も簡単な方法はおそらくディスクリミネーターフィールドを作成することです。

      Alpha
      --------
   PK AlphaId
   PK AlphaType NOT NULL IN ("Bravo", "Charlie")
      AlphaOne
      AlphaTwo
      AlphaThree

      Bravos
      --------
FK PK AlphaId
FK PK AlphaType == "Bravo"
      BravoOne
      BravoTwo
      BravoThree

      Charlies
      --------
FK PK AlphaId
FK PK AlphaType == "Charlie"
      CharlieOne
      CharlieTwo
      CharlieThree

このように、AlphaTypeフィールドは、レコードが常に正確に1つのサブタイプに属するように強制します。

于 2008-09-11T17:58:12.453 に答える
4

SQL Server 2000 / 2005 を使用すると想定しています。私が使用する 1 対 1 の関係の標準パターンがありますが、これは 2 番目のアイデアとあまり似ていませんが、違いは次のとおりです。

  • すべてのエンティティは最初に独自の主キーを持つ必要があるため、Bravo、Charlie などのテーブルは、Alpha テーブルの外部キー列に加えて、独自の代理キーを定義する必要があります。あるテーブルの主キーが別のテーブルの主キーとまったく同じでなければならないことを指定することで、ドメイン モデルを非常に柔軟性のないものにしています。したがって、エンティティは非常に密結合になり、あるエンティティが別のエンティティなしでは存在できなくなります。これは、データベース設計内で実施する必要があるビジネス ルールではありません。

  • Bravo テーブルと Charlie テーブルの AlphaID 列間の外部キー制約を、Alpha テーブルの主キー列に追加します。これにより、1 対多が可能になり、FK 列の null 可能性を設定するだけでリレーションシップが必須かどうかを指定することもできます (現在の設計では不可能なことです)。

  • AlphaID 列のテーブル Bravo、Charlie などに一意キー制約を追加します。これにより、1 対 1 の関係が作成され、一意のキーがインデックスとしても機能し、外部キーの値に基づいて行を取得するクエリを高速化するのに役立つという利点が追加されます。

このアプローチの主な利点は、変更が容易になることです。

  • 1 対多に戻したいですか? 関連する一意のキーを削除するか、通常のインデックスに変更します
  • ブラボーをアルファから独立して存在させたいですか?すでに代理キーを取得しています。AlphaID FK 列を NULL を許可するように設定するだけです。
于 2008-09-22T05:24:49.773 に答える
3

個人的には、単一の列で PK/FK を使用して、2 番目のモデルで多くの成功を収めました。

すべてのアルファが Bravo または Charlie テーブルにレコードを持っている必要があるという状況は一度もありませんでした。私は常に 1 <-> 0..1 を扱ってきましたが、1 <-> 1 は扱ったことはありません。

最後の質問ですが、それはテーブルがたくさんあるということです。

于 2008-09-11T17:41:57.967 に答える
1

これまでのところ、モデルに適合する非常にうまく機能する例があります。

Alpha からの外部キー alpha_id を持つ Charlie テーブルと Bravo テーブルがあります。最初の例と同様に、alpha が主キーではないことを除いて、bravo_id と charlie_id はそうです。

これらのエンティティに対処する必要があるすべてのテーブルで alpha_id を使用するため、Bravo と Charlie の両方を調査してどれが Alpha であるかを調べるのに遅延が生じる可能性がある SQL を回避するために、AlphaType テーブルを作成し、Alpha テーブルにその ID を持っています(alpha_type_id) を外部キーとして。そうすれば、無数のレコードを持つ可能性のあるテーブルを結合することなく、どの AlphaType を扱っているかをプログラムで知ることができます。tSQL で:

// For example sake lets think Id as a CHAR.
// and pardon me on any mistake, I dont have the exact code here,
// but you can get the idea

SELECT 
  (CASE alpha_type_id
    WHEN 'B' THEN '[Bravo].[Name]'
    WHEN 'C' THEN '[Charlie].[Name]'
    ELSE Null
  END)
FROM ...
于 2008-09-11T22:07:43.147 に答える
1

もう 1 つのアプローチは、3 つのエンティティを格納するための 3 つのテーブルと、関係を格納するための別のテーブルを用意することです。

于 2008-09-11T17:40:57.983 に答える
1

Alpha と関連 ID を指定する結合テーブルを持つことができます。次に、ブラボー、チャーリーなどの ID であるかどうかを指定する別の列を追加できます。Alpha では列のクリープ ダウンを維持しますが、クエリの結合がいくらか複雑になります。

于 2008-09-11T17:42:13.240 に答える
1

解決しようとしている正確な問題をさらに明確にしないと、提案されたソリューションを選択するのが難しくなる多くの質問を提起します。明確化のための質問だけでなく、問題を解決するために必要な詳細の量を示すものとして、私の質問を評価するために使用する基準を考慮してください。

  • 習得と保守が容易なシステム。

習得と保守が容易な「システム」とは? アプリのソース コードですか、それともエンド ユーザー インターフェースを介したアプリのデータですか?

  • データベース内で実施されるデータの整合性。

「データベース内で強制」とはどういう意味ですか? これは、他の方法でデータの整合性を制御することは決してできないということですか。つまり、プロジェクトには DB ベースのデータ整合性ルールしか必要ありませんか?

  • 私のデータの実世界の論理的な編成に一致するスキーマ。

あなたが言及している現実世界の論理的な組織を教えていただけますか? 保存しようとしているデータの 3 つの例からそれを推測することは不可能です。つまり、3 つの構造すべてが完全に間違っているとします。実際の仕様を知らなければ、どうやってそれを知ることができるでしょうか?

  • 私のプログラミング内のクラス/オブジェクトは、データベース テーブルに適切にマップされます (Linq から SQL に似ています)

この要件は、あなたの手が linq to SQL でこれを作成することを余儀なくされているように聞こえますが、そうですか?

  • 高速な読み取りおよび書き込み操作

「スピーディー」とは?0.03秒? 3秒?30分?参照しているデータサイズと操作の種類を指定していないため、不明です。

  • スペースの有効利用 (null フィールドが少ない)

スペースの有効利用は、null フィールドの数とは関係ありません。正規化されたデータベース構造を意味する場合、それは、質問で提供されていない実際の仕様やアプリケーションのその他の設計要素に再び依存します。

于 2008-09-17T19:04:08.297 に答える
0

特別な理由がない限り、オプション1を選択します。特に、思ったほどのスペースは必要ないかもしれません。Bravoでvarcharsを使用している場合。分割すると、外部キー、セカンダリID、および必要なインデックスのコストがかかることを忘れないでください。

問題が発生する可能性があるのは、Bravoが必要になる可能性が低く(<%10)、そのフィールドの1つですばやくクエリを実行して、インデックスを作成する必要がある場合です。

于 2008-09-11T17:48:23.257 に答える
0

スーパータイプ/サブタイプの関係を作成します。

   THINGS
   ------
PK ThingId  

   ALPHAS
   ------
FK ThingId (not null, identifying, exported from THINGS)
   AlphaCol1
   AlphaCol2
   AlphaCol3  

   BRAVOS
   ------
FK ThingId (not null, identifying, exported from THINGS)
   BravoCol1
   BravoCol2
   BravoCol3  

   CHARLIES
   --------
FK ThingId (not null, identifying, exported from THINGS)
   CharlieCol1
   CharlieCol2
   CharlieCol3

したがって、たとえば、チャーリーがいるがブラボーがないアルファ:-

insert into things values (1);
insert into alphas values (1,'alpha col 1',5,'blue');
insert into charlies values (1,'charlie col 1',17,'Y');

ThingId が 1 の 2 つのチャーリーを作成しようとすると、2 番目の挿入で一意のインデックス/制約違反が発生するため、アルファ用に複数のチャーリーを作成することはできないことに注意してください。

于 2008-09-17T18:13:16.407 に答える