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_id
i parent_id
są kluczami obcymi do tabel encji. Sama tabela „podrzędna” zawiera także klucz obcy do tabeli „nadrzędnej”, a lo child_id
zawsze odnosi się do tego samego, parent_id
jak 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_id
muszą 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:
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.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?
Odpowiedzi:
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.
źródło
Spróbuj tego...
(child_id,parent_id)
tabeli potomnej(PK,FK:child_id, PK,FK:parent_id, PK:date)
pozostaje niezmieniony, FK jest na 2 kolumnach z nowym unikalnym ograniczeniemlub
(PK,FK:child_id, FK:parent_id)
który jest 1: 1 z dzieckiem(PK,FK: child_id, PK,FK: parent_id, PK:date)
pozostaje niezmieniony. ale FK jest na 2 kolumnach do nowej tabeliJeśli nic więcej, może cię zainspirować ...
Jeśli dobrze zrozumiałem, usunie nadmiarowość i kod ...
źródło