複数の関係に対して1つのテーブルを用意するべきではないのはなぜですか?


12

データベースにStore、Employee、Saleなどの複数のリレーションがあり、ペアを単純なバイナリリレーションで接続するとします。個人的には、外部キーで構成される自然キーを使用して、Employee_StoreおよびEmployee_Saleという名前のテーブルを作成します。

現在、私の同僚は、複数のリレーションシップ用に1つのテーブルを作成することを強く求めています。上記の例の場合、EmployeeLinksというテーブルがある可能性があります。

EmployeeLinks(
    IdLink int PK, 
    IdEmployee int FK null,
    IdStore int FK null,
    IdSale int FK null,
    LinkType int not null
)

これが良い考えではない理由を教えてください。私は自分の主張を持っていますが、私はそれらを非公開にし、あなたの公平な意見を聞きたいと思います。

編集:

最初、上のテーブルには主キー(!)がありません。外部キーはnullを許可するため、代理キーが唯一のオプションです。


3
それはOTLTやEAVに似ていますが、行ではなく列を増殖させるため、さらに悪いです!
onedaywhen

回答:


13

あなたの同僚は、このリンクテーブルの主キーとして何を提案していますか?
もちろん、主キー列をNULLにすることはできません。上記の表はNULL可能です。

上記の例では(PKとは)自然な行識別子がないため(IDENTITY列は主キーではありません)、そのため、どのモデリングプロセスで失敗します。いくつかのモデル(ERD、ORM、IDEF1Xなど)なしでテーブルを作成することさえ考えないでください

また、3方向リンクがないことを確認するには、CHECK制約も必要です。

最後に、あなたは4番目と5番目の通常形式の領域に迷い込んでいますが、理由は間違っています。

私はインターネットで例を見つけることができません:これはこれがどれほど愚かであることを示しています


4
+1I can't find any examples on the internet: that shows how stupid this is
JNK

主キーについてより明確にしました。また、どうやら私の同僚は実際にそのようなデザインに実際に出会ったことがあると聞いています
Tomasz Pluskiewicz

@Tomasz Pluskiewicz:代理キーは主キーではありません!これは、実装時に自然キーを補完するために選択されます。dba.stackexchange.com/a/13779/630を参照してくださいまた、この手法を実証する信頼できる記事を同僚から紹介してもらう必要があります。私は自分の時間に完全なゴミの山を見てきましたが、繰り返しはしません...
gbn

12

私が考えることができる最初の実用的な理由はパフォーマンスです。

「従来の」モデルでIdemployee, Idstoreは、フィールドに一意のインデックスを付けることができ、ルックアップで優れたパフォーマンスを得ることができます。インサートのメンテナンスも簡単です。一意のインデックスを使用すると、結合をより頻繁にマージできるため、多くのJOINs が非常に高速になります。

適切なパフォーマンスを得るには、モデルの例では、テーブル内のすべてのFKフィールドに単一のフィールドインデックスを設定する必要があります。理想的には、参照されるすべての組み合わせをカバーするインデックスです。

  • 社員・店舗
  • 従業員/販売

linktypeが何であるかはわかりませんが、参照する場合は、おそらく索引付けする必要があります。

これらのインデックスは、フィールドに値が入力されているかどうかに関係なく、テーブルのすべての行で維持する必要があります。フィルターを追加することもできますが、組み合わせが多すぎるとトリッキーになります。

また、ロジックが複雑になります。 employeeidでルックアップを実行し、ストアの値が空の行を見つけて更新する必要があります。または、新しいリンクごとに新しい行を挿入するだけで、フィールドを統合する目的が損なわれます。

基本的には、より多くのディスク領域を使用し、維持するインデックスがより多くなり、基本的に理由もなくロジックが複雑になります。唯一の「メリット」は、処理するテーブルが少ないことです。


LinkTypeカラムは、判別のようなものです。行が実際に関連しているペアを伝えるだけです。あなたが私に尋ねるならば、ちょうど仕掛けに加えます。
Tomasz Pluskiewicz

@TomaszPluskiewicz私が彼にそれが悪い理由を示す最良の方法は、両方の種類のテーブルを含むサンプルデータセットを構築し、いくつかのクエリを実行することだと思います。彼のモデルは、従来のモデルよりもはるかに遅くなります
JNK

4

複数のリレーションシップを1つのテーブルに入れると、それらのリレーションシップが同じ属性を持つ場合や、複数のリレーションシップにわたってデータを集計する場合に便利です。

関係のタイプが実行時にユーザーによって定義される場合に必要です。ただし、これが実際に起こることはまれです。

あなたの例では、リレーションシップは属性を共有せず、リレーションシップは2つの異なるテーブルを参照しています。これにより、制約を適用することが困難になり、設計も直感的ではなくなります。

テーブルの作成に文字通りコストがかかる場合のみ、私はそのデザインを選択しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.