Czy mogę bezstratnie rozłożyć ten stół?

10

Natknąłem się na problem z projektowaniem bazy danych, który jest poza moją ligą, a mój guru DBA bierze udział w ćwiczeniach przeciwpożarowych.

Zasadniczo mam tabelę z następującym kluczem podstawowym (PK dla zwięzłości):

child_id   integer
parent_id  integer
date       datetime

child_idi parent_idsą kluczami obcymi do tabel encji. Sama tabela „podrzędna” zawiera także klucz obcy do tabeli „nadrzędnej”, a lo child_idzawsze odnosi się do tego samego, parent_idjak oczekiwano w powyższej tabeli. W rzeczywistości okazuje się, że jest jakiś dodatkowy kod, który utrzymuje synchronizację między nimi.

Co sprawia, że ​​ten nadmiernie entuzjastyczny nowicjusz normalizacyjny mówi: „Zamiast tego powinienem usunąć redundancję!”

Rozkładam się na następujące:

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

A kiedy dołączę do nich w naturalny sposób, odzyskuję oryginalny stół. Z mojego zrozumienia wynika, że ​​to 5NF.

Teraz jednak zdaję sobie sprawę, że istnieje ukryta zasada biznesowa.

Zazwyczaj daty powiązane z danym child_idmuszą być podzbiorem dat powiązanych z odpowiednim parent_id. Widać, że pierwsza tabela wymusza tę regułę.

Mój rozkład nie wymusza reguły, ponieważ możesz swobodnie dodawać do tabeli 1, dopóki daty nie staną się zbyt duże.

Co prowadzi mnie tutaj z następującymi pytaniami:

  1. Czy to rozkład 5NF? Chociaż powiedziałbym, że pozwala na anomalie wstawiania, wydaje się, że podąża za przykładem Wiki, który sam podąża za tym przewodnikiem . Wyrażenie (moje podkreślenie) „możemy zrekonstruować wszystkie prawdziwe fakty ze znormalizowanej formy składającej się z trzech oddzielnych typów rekordów” daje mi specjalną pauzę, ponieważ bez względu na to, jak dużo śmieci wpompowuję Table_1, naturalne połączenie wciąż je ignoruje.

  2. Załóżmy, że nie podoba mi się ten rozkład (nie lubię). Przyjmuję do wiadomości, że praktycznym rozwiązaniem jest pozostawienie tabeli i kodu bez zmian. Ale teoretycznie, czy istnieje sposób na rozłożenie i / lub dodanie ograniczeń, aby oderwać się od pierwszego stołu i zachować zasady biznesowe?

trevor
źródło
1
Jakie są klucze w twoim oryginalnym stole? Jakie zależności ma satyfikować? Wydaje się, że mówisz, że child_id-> parent_id, w którym to przypadku child_id i parent_id nie mogą być częścią tego samego klucza w tej tabeli.
nvogel
1
@trevor: Czy kiedykolwiek przejrzałeś tutaj odpowiedzi? Ostatnio widziany 19 minut po zapytaniu. Odpowiedzi nadeszły później.
gbn

Odpowiedzi:

9

Normalizacja opiera się na zależnościach funkcjonalnych. Zależności funkcjonalne mają związek z semantyką; mają one związek z tym, co oznaczają dane . Gdy uprościsz rzeczywisty problem do poziomu „parent_id, child_id, date” i nie podasz żadnych przykładowych danych, naprawdę ograniczysz zakres pomocy, jaką może zaoferować sumienny projektant bazy danych.

Fakt, że masz klucz {child_id, parent_id, date} w jednej tabeli i że masz (wydaje się) unikalną parę {child_id, parent_id} w tabeli potomnej, niekoniecznie oznacza, że ​​część kombinacji jest zbędna . Może to oznaczać, że w tabeli, która ma {child_id, parent_id, date} jako klucz podstawowy, para atrybutów {child_id, parent_id} powinna przede wszystkim odwoływać się do tabeli potomnej.

W takim przypadku możesz użyć FOREIGN KEY (child_id, parent_id) REFERENCES child (child_id, parent_id). Aby to zrobić, potrzebujesz ograniczenia UNIQUE dla pary kolumn (child_id, parent_id) w tabeli „child”, co nie powinno stanowić problemu, jeśli child_id jest jego kluczem podstawowym.

Ale nie można tego powiedzieć bez wiedzy, co oznaczają dane, a ty jesteś jedynym w tym wątku, który to wie. (Ale chętnie Ci wyjaśnimy.)

Jeśli chodzi o oryginalną tabelę, wydaje się, że mówisz, że child_id -> parent_id. Jeśli tak, to dlaczego w pierwszej kolejności jest parent_id w oryginalnej tabeli? Dlaczego klucz nie jest po prostu (child_id, date) z odniesieniem do klucza obcego do tabeli „child”? Wydaje mi się, że rodzaj nadmiarowości, o którym mówisz, można rozwiązać, upuszczając kolumnę „parent_id”.

SQL DDL i przykładowe dane w postaci instrukcji INSERT pomagają nam pomóc. Instrukcje DDL i INSERT są bardziej precyzyjne niż opisy.

Mike Sherrill „Cat Recall”
źródło
1
+2 za przypomnienie „funkcjonalna zależność”
jcolebrand
3

Spróbuj tego...

  • Dodaj unikalne ograniczenie do (child_id,parent_id)tabeli potomnej
  • Twój aktualny stół (PK,FK:child_id, PK,FK:parent_id, PK:date)pozostaje niezmieniony, FK jest na 2 kolumnach z nowym unikalnym ograniczeniem

lub

  • Usuń FK z bieżącej tabeli podrzędnej
  • Utwórz nowy stół, (PK,FK:child_id, FK:parent_id)który jest 1: 1 z dzieckiem
  • Twój obecny stół (PK,FK: child_id, PK,FK: parent_id, PK:date)pozostaje niezmieniony. ale FK jest na 2 kolumnach do nowej tabeli

Jeśli nic więcej, może cię zainspirować ...

Jeśli dobrze zrozumiałem, usunie nadmiarowość i kod ...

gbn
źródło