web-dev-qa-db-ja.com

このテーブルを無損失で分解できますか?

私は自分のリーグではないデータベース設計の問題に遭遇しました。私のDBAの第一人者は消防訓練に出かけています。

本質的に、私は次の主キー(簡潔にするためにPK)を持つテーブルを持っています。

child_id   integer
parent_id  integer
date       datetime

child_idおよびparent_idは、エンティティテーブルへの外部キーです。 「子」テーブル自体にも「親」テーブルへの外部キーが含まれています。loは、それぞれのchild_idが常に上記のテーブルで予想される同じparent_idを参照します。実際、この2つを同期させるための追加のコードがあることがわかります。

これにより、この熱狂的な正規化の初心者は「代わりに冗長性を削除する必要があります」と言います。

次のように分解します。

Table_1 PK:
child_id   integer
date       datetime

Table_2 PK:
parent_id  integer
date       datetime

Table_3: (already exists)
child_id   integer PRIMARY KEY
parent_id  integer FOREIGN KEY

そして、これらの人たちを自然な方法で結合すると、元のテーブルが回復します。この5NFを作ったのは私の理解です。

しかし、今ではビジネスルールが隠されていることに気づきました。

通常、特定のchild_idに関連付けられている日付は、対応するparent_idに関連付けられている日付のサブセットである必要があります。最初のテーブルがこのルールを適用していることがわかります。

日付が大きくなりすぎるまで自由に表1に追加できるため、私の分解ではルールを適用しません。

これは私をここに導き、次の質問があります:

  1. この分解は5NFですか?挿入の異常を許容すると私は言いますが、それは このガイド に従っているWikiの例にも従っているようです。 (強調鉱山)「3つの別個のレコードタイプで構成される正規化された形式からすべてのtrueファクトを再構築できます」というフレーズは、特別な一時停止を与えます。どれだけのガベージをTable_1に送り込んでも、自然結合はそれを無視します。

  2. この分解が気に入らないとしましょう(気に入らない)。テーブルとコードをそのままにしておくことが実際的な解決策であることを私は自由に認めます。しかし、理論的には、最初のテーブルから離れビジネスルールを保持するように、制約を分解または追加する方法はありますか?

10
trevor

正規化は、機能の依存関係に基づいています。機能の依存関係はセマンティクスと関係があります。彼らはデータ手段と関係があります。実際の問題を「parent_id、child_id、date」のレベルに簡略化し、サンプルデータを含めない場合、良心的なデータベース設計者が提供できるヘルプの量が本当に制限されます。

1つのテーブルにキー{child_id、parent_id、date}があり、子テーブルに一意のペア{child_id、parent_id}がある(と思われる)ことは、必ずしも組み合わせの一部が冗長であることを意味するわけではありません。 {child_id、parent_id、date}を主キーとするテーブルでは、最初に属性のペア{child_id、parent_id}が子テーブルを参照する必要があることを意味する場合があります。

その場合は、FOREIGN KEY (child_id, parent_id) REFERENCES child (child_id, parent_id)を使用できます。これを行うには、テーブル "child"の列のペア(child_id、parent_id)にUNIQUE制約が必要です。これは、child_idが主キーである場合は問題になりません。

しかし、データが何を意味するのかを知らずに判断する方法はありません。あなたはこのスレッドでそれを知っている唯一の人です。 (ただし、説明させていただきます。)

元のテーブルに関する限り、そのchild_id-> parent_idと言っているようです。その場合、元のテーブルのparent_idがそもそもなぜですか。キーが(child_id、date)だけではなく、「子」テーブルへの外部キー参照があるのはなぜですか?あなたが話している冗長性の種類は、列「parent_id」を削除することで解決できるようです。

SQL DDLとINSERTステートメント形式のサンプルデータは、私たちを支援します。 DDLおよびINSERTステートメントは、説明よりも正確です。

これを試して...

  • 子テーブルの(child_id,parent_id)に一意の制約を追加します
  • 現在のテーブル(PK,FK:child_id, PK,FK:parent_id, PK:date)はそのままで、FKは新しい一意制約の2列にあります

または

  • 現在の子テーブルからFKを削除します
  • 子を持つ1:1の新しいテーブル(PK,FK:child_id, FK:parent_id)を作成します
  • 現在のテーブル(PK,FK: child_id, PK,FK: parent_id, PK:date)はそのままです。しかし、FKは新しいテーブルの2列にあります

他に何もなければ、それはあなたを刺激するかもしれません...

私が正しく理解していれば、冗長性とコードが削除されます...

3
gbn