1

私は次の構造を持っています:

Block A
  Foo 1
    Bar 1
    Bar 2
  Foo 2
    Bar 1
    Bar 3
  Bar 4

Block B
  Foo 3
  • すべての Foo は正確に on Block に属します。
  • すべてのバーは正確にブロックに属します。
  • Barは、同じ Blockの 1 つまたは複数の Foo に属することができません。

スキーマは現在次のようになっています。

    Block
   1/   \1
  n/     \n
Foo-n---m-Bar

これに関する問題は、異なるブロックの Foo に属する Bar が存在する可能性があることです。

冗長性も矛盾も許容しないスキーマはありますか?

4

3 に答える 3

5

はい、方法はあります。の主キー列をBlock関連付けテーブルに含め、それを使用して外部キー制約を拡張します。

CREATE TABLE Blocks
  ( BlockID INT 
  , PRIMARY KEY (BlockID)
  ) ;

CREATE TABLE Foos
  ( BlockID INT
  , FooID INT
  , PRIMARY KEY (FooID)
  , FOREIGN KEY (BlockID)
      REFERENCES Blocks (BlockID)
  , UNIQUE (BlockID, FooID)              -- the Unique constraints are needed for 
  ) ;

CREATE TABLE Bars
  ( BlockID INT
  , BarID INT
  , PRIMARY KEY (BarID)
  , FOREIGN KEY (BlockID)
      REFERENCES Blocks (BlockID)
  , UNIQUE (BlockID, BarID)              -- the composite FKs below
  ) ;

CREATE TABLE Foo_Bars                    -- the m:n association tabletable
  ( BlockID INT
  , FooID INT
  , BarID INT
  , PRIMARY KEY (FooID, BarID)
  , FOREIGN KEY (BlockID, FooID)         -- composite FK constraints to Foos
      REFERENCES Foos (BlockID, FooID)
  , FOREIGN KEY (BlockID, BarID)         -- and Bars
      REFERENCES Bars (BlockID, BarID)
  ) ;
于 2013-10-21T16:57:40.703 に答える
2

ypercube が言ったこと (彼に +1、BTW) に加えて、キーの構造を変更したい場合は、インデックスのオーバーヘッドを減らすことができます。

ここに画像の説明を入力

FOO_BAR.BLOCK_ID は BLOCK まで両方の「ブランチ」を参照するため、FOO と BAR が接続されている場合は、それらも同じBLOCK に接続されている必要があります。

(元の質問の範囲外で)必要な追加のインデックスがない限り、この構造は非常に効率的にクラスター化できます。

于 2013-10-22T12:01:49.730 に答える
1

私が正しく理解している場合、次のような状況があります。

block_foo_bar

block   foo bar
A       1   1
A       1   2
A       2   1
A       2   3
A       0A  4
B       3   0B
  • 不足している要素を表すダミーの Foo と Bar に ID 0 を使用しました (必要に応じて NULL を使用できます)。

このようなテーブルは nm を処理しますが、1-n の関係を強制することはできません。

私の提案は、2 つの追加のテーブルを作成することです。

block_foo

block(FK) foo(PK)
A         0A
A         1
A         2
B         0B
B         3

block_bar

block(FK) bar(PK)
A         0A
A         1
A         2
A         3
A         4
B         0B

このようにして、2 つの新しいテーブルは for/bar-block 関係の一意性を強制します。block_foo_bar を使用すると、nm 関係を処理できます。block_foo テーブルと block_bar テーブルで許可されていないリレーションシップが block_foo_bar に含まれないようにするために、block_foo_bar に 2 つの制約を作成します。

  • block_foo_bar_FK1 = block - block_foo テーブルの foo
  • block_foo_bar_FK2 = ブロック - block_bar テーブルのバー

お気づきかもしれませんが、0A や 0B のようなダミー ID を作成したのは、null 可能な ID は決して良い考えではないためです。次に、このようにして ID に PK を適用できるためです。これは、Foo/Bar テーブルに Foo/Bar のないブロックごとにダミー レコードを作成することを意味することを理解しています (ETL の作業が増えます)。

私の説明があなたにとって理にかなっていることを願っています。

于 2013-10-21T15:08:31.913 に答える