Kann ich diese Tabelle verlustfrei zerlegen?

10

Ich bin auf ein Datenbankdesignproblem gestoßen, das nicht in meiner Liga liegt, und mein DBA-Guru ist auf Feuerübungen.

Im Wesentlichen habe ich eine Tabelle mit dem folgenden Primärschlüssel (PK der Kürze halber):

child_id   integer
parent_id  integer
date       datetime

child_idund parent_idsind Fremdschlüssel für Entitätstabellen. Die "untergeordnete" Tabelle selbst enthält auch einen Fremdschlüssel für die "übergeordnete" Tabelle, und siehe da, jeder child_idverweist immer auf den gleichen Wert, parent_idwie in der obigen Tabelle erwartet. Es stellt sich heraus, dass es einen zusätzlichen Code gibt, der die beiden synchron hält.

Was diesen überbegeisterten Normalisierungsanfänger dazu bringt, zu sagen: "Ich sollte stattdessen die Redundanz entfernen!"

Ich zerlege mich in folgendes:

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

Und siehe da, wenn ich diese Leute auf natürliche Weise zusammenbringe, stelle ich den ursprünglichen Tisch wieder her. Es ist mein Verständnis, das diesen 5NF ausmacht.

Jetzt ist mir jedoch klar, dass es eine versteckte Geschäftsregel gibt.

Normalerweise müssen die mit einem bestimmten child_idDatum verknüpften Daten eine Teilmenge der mit dem entsprechenden Datum verknüpften Daten sein parent_id. Sie können sehen, dass die erste Tabelle diese Regel erzwingt.

Meine Zerlegung erzwingt die Regel nicht, da Sie Tabelle 1 frei hinzufügen können, bis die Daten zu groß werden.

Was mich hierher führt, mit folgenden Fragen:

  1. Ist diese Zersetzung 5NF? Ich würde zwar sagen, dass es Einfügeanomalien zulässt, aber es scheint auch dem Wiki-Beispiel zu folgen, das selbst dieser Anleitung folgt . Der Satz (Hervorhebung von mir) "Wir können alle wahren Tatsachen aus einer normalisierten Form rekonstruieren, die aus drei getrennten Datensatztypen besteht" gibt mir eine besondere Pause, da Table_1die natürliche Verbindung sie immer noch ignoriert , egal wie viel Müll ich hineinpumpe.

  2. Angenommen, ich mag diese Zerlegung nicht (ich nicht). Ich erkenne frei an, dass die praktische Lösung darin besteht, die Tabelle und den Code so zu belassen, wie sie sind. Aber gibt es theoretisch eine Möglichkeit, Einschränkungen so zu zerlegen und / oder hinzuzufügen, dass ich mich von der ersten Tabelle entferne und meine Geschäftsregeln behalte?

Trevor
quelle
1
Was sind die Schlüssel in Ihrer Originaltabelle? Welche Abhängigkeiten soll es befriedigen? Sie scheinen zu sagen, dass child_id-> parent_id. In diesem Fall können child_id und parent_id nicht beide Teil desselben Schlüssels in dieser Tabelle sein.
Nvogel
1
@trevor: Hast du jemals die Antworten hier überprüft? Zuletzt gesehen 19 Minuten nach der Frage. Die Antworten kamen später.
Gbn

Antworten:

9

Die Normalisierung basiert auf funktionalen Abhängigkeiten. Funktionale Abhängigkeiten haben mit Semantik zu tun; Sie haben damit zu tun, was die Daten bedeuten . Wenn Sie ein reales Problem auf die Ebene "parent_id, child_id, date" vereinfachen und keine Beispieldaten angeben, schränken Sie die Hilfe eines gewissenhaften Datenbankdesigners wirklich ein.

Die Tatsache, dass Sie einen Schlüssel {child_id, parent_id, date} in einer Tabelle haben und (wie es scheint) ein eindeutiges Paar {child_id, parent_id} in der untergeordneten Tabelle haben, bedeutet nicht unbedingt, dass ein Teil der Kombination redundant ist . Dies kann bedeuten, dass in der Tabelle mit {child_id, parent_id, date} als Primärschlüssel das Attributpaar {child_id, parent_id} zunächst auf die untergeordnete Tabelle verweisen sollte.

Wenn dies der Fall ist, können Sie verwenden FOREIGN KEY (child_id, parent_id) REFERENCES child (child_id, parent_id). Dazu benötigen Sie eine EINZIGARTIGE Einschränkung für das Spaltenpaar (child_id, parent_id) in der Tabelle "child". Dies sollte kein Problem sein, wenn child_id der Primärschlüssel ist.

Aber es gibt keine Möglichkeit zu sagen, ohne zu wissen, was die Daten bedeuten, und Sie sind der einzige in diesem Thread, der das weiß. (Aber wir würden uns freuen, wenn Sie es uns erklären.)

In Bezug auf die ursprüngliche Tabelle scheinen Sie zu sagen, dass child_id -> parent_id. Wenn dies der Fall ist, warum steht parent_id überhaupt in der Originaltabelle? Warum ist der Schlüssel nicht nur (child_id, date) mit einem Fremdschlüsselverweis auf die "child" -Tabelle? Für mich scheint die Art der Redundanz, von der Sie sprechen, durch Löschen der Spalte "parent_id" behoben zu werden.

SQL DDL und Beispieldaten in Form von INSERT-Anweisungen helfen uns dabei. DDL- und INSERT-Anweisungen sind präziser als Beschreibungen.

Mike Sherrill 'Cat Recall'
quelle
1
+2 für "funktionale Abhängigkeit" Erinnerung
jcolebrand
3

Versuche dies...

  • Fügen Sie (child_id,parent_id)der untergeordneten Tabelle eine eindeutige Einschränkung hinzu
  • Ihre aktuelle Tabelle (PK,FK:child_id, PK,FK:parent_id, PK:date)bleibt unverändert, die FK befindet sich in 2 Spalten für die neue eindeutige Einschränkung

oder

  • Entfernen Sie den FK aus der aktuellen untergeordneten Tabelle
  • Erstellen Sie eine neue Tabelle (PK,FK:child_id, FK:parent_id), die 1: 1 mit dem Kind ist
  • Ihre aktuelle Tabelle (PK,FK: child_id, PK,FK: parent_id, PK:date)bleibt unverändert. Die FK befindet sich jedoch in zwei Spalten zur neuen Tabelle

Wenn nichts anderes, kann es Sie inspirieren ...

Wenn ich es richtig verstanden habe, werden Redundanz und Code entfernt ...

gbn
quelle