Muszę wymodelować sytuację, w której mam tabelę Chequing_Account (która zawiera budżet, numer iban i inne szczegóły konta), która musi być powiązana z dwiema różnymi tabelami Osoba i Korporacja, które mogą mieć 0, 1 lub wiele kont sprawdzających.
Innymi słowy, mam dwa relacje 1 do wielu z tym samym kontem Chequing w tabeli
Chciałbym usłyszeć rozwiązania tego problemu, które spełniają wymogi normalizacji. Większość rozwiązań, o których słyszałem, to:
1) znajdź wspólny podmiot, do którego należą zarówno Osoba, jak i Korporacja, i utwórz tabelę łączy między tą tabelą a tabelą Chequing_Account, w moim przypadku nie jest to możliwe, a nawet gdyby tak było, chcę rozwiązać ogólny problem, a nie tę konkretną instancję.
2) Utwórz dwie tabele łączy PersonToChequingAccount i CorporationToChequingAccount, które łączą te dwa podmioty z Kontami Chequing. Jednak nie chcę, aby dwie osoby miały to samo konto sprawdzające, i nie chcę, aby osoba fizyczna i korporacja dzieliły się kontem sprawdzającym! zobacz ten obraz
3) Utwórz dwa klucze obce na koncie Chequing, które wskazują korporację i osobę fizyczną, jednak wymusiłbym w ten sposób, że osoba i firma mogą mieć wiele kont sprawdzania, jednak musiałbym ręcznie upewnić się, że dla każdego wiersza ChequingAccount nie oba relacje wskazują Korporacja i osoba fizyczna, ponieważ rachunek kontrolny jest albo korporacją, albo osobą fizyczną. zobacz ten obraz
Czy jest jakieś inne czystsze rozwiązanie tego problemu?
źródło
OwnerTypeID
PrzyChecquingAccount
stole z,1=Corporation
i2=NaturalPerson
? W ten sposób potrzebujesz tylko jednegoOwnerID
wChecquingAccount
tabeli, który możesz indeksować wraz zOwnerTypeID
.CHECK (CorporationID IS NOT NULL AND NaturalPersonID IS NULL OR CorporationID IS NULL AND NaturalPersonID IS NOT NULL)
zdecydowanie wolę rozwiązanie 1 (ale to tylko ja). Jest o wiele „czystszy”.ChecquingAccount
tabeli zapisOwnerTypeID=1
iOwnerID=123
, wskazując, że jest to typCorporation
, a zatem identyfikator123
wCorporation
tabeli. OwnerTypeID powie Ci, która tabela, a OwnerID powie Ci ID w tej tabeli.Customers
stołem.Odpowiedzi:
Relacyjne bazy danych nie są budowane, aby doskonale poradzić sobie z tą sytuacją. Musisz zdecydować, co jest dla Ciebie najważniejsze, a następnie dokonać kompromisu. Masz kilka celów:
Problem polega na tym, że niektóre z tych celów konkurują ze sobą.
Rozwiązanie do podtypowania
Możesz wybrać rozwiązanie do podtytułu, w którym tworzysz supertyp, który obejmuje zarówno korporacje, jak i osoby. Ten nadtyp prawdopodobnie miałby klucz złożony z klucza naturalnego podtypu plus atrybut partycjonowania (np
customer_type
.). Jest to w porządku, o ile chodzi o normalizację, i pozwala egzekwować integralność referencyjną, a także ograniczenie wzajemnego wykluczania się korporacji i osób. Problem polega na tym, że utrudnia to pobieranie danych, ponieważ zawsze musisz rozgałęzić się na podstawiecustomer_type
momentu dołączenia konta do właściciela konta. Prawdopodobnie oznacza to używanieUNION
i powtarzanie zapytania w zapytaniu.Rozwiązanie z
dwoma kluczami obcymi Możesz wybrać rozwiązanie, w którym przechowujesz dwa klucze obce w tabeli rachunków, jeden dla korporacji i jeden dla osoby. To rozwiązanie pozwala również zachować integralność referencyjną, normalizację i wzajemną wyłączność. Ma również tę samą wadę pobierania danych, co rozwiązanie do podtypów. W rzeczywistości to rozwiązanie jest podobne do podtytułu, z tą różnicą, że masz problem z rozgałęzieniem logiki łączenia „wcześniej”.
Niemniej jednak wielu modelarzy danych uznałoby to rozwiązanie za gorsze od rozwiązania podtypów z uwagi na sposób egzekwowania ograniczenia wzajemnej wyłączności. W rozwiązaniu do podtypowania tekstu używasz kluczy do egzekwowania wzajemnej wyłączności. W dwóch rozwiązaniach z kluczem obcym używasz
CHECK
ograniczenia. Znam niektórych ludzi, którzy mają nieuzasadnione uprzedzenia wobec ograniczeń czekowych. Ci ludzie wolą rozwiązanie, które utrzymuje ograniczenia w kluczach.Rozwiązanie „zdenormalizowanego” atrybutu partycjonowania
Istnieje jeszcze jedna opcja, w której trzymasz jedną kolumnę klucza obcego w tabeli kont sprawdzających i używasz innej kolumny, aby powiedzieć ci, jak interpretować kolumnę klucza obcego (RoKa's
OwnerTypeID
kolumna). To zasadniczo eliminuje tabelę supertypu w rozwiązaniu podtypowania przez denormalizowanie atrybutu partycjonowania do tabeli potomnej. (Należy zauważyć, że zgodnie z formalną definicją nie jest to ściśle „denormalizacja”, ponieważ atrybut partycjonowania jest częścią klucza podstawowego.) To rozwiązanie wydaje się dość proste, ponieważ unika się konieczności posiadania dodatkowej tabeli w celu wykonania mniej więcej tej samej rzeczy i to zmniejsza liczbę kolumn klucza obcego do jednego. Problem z tym rozwiązaniem polega na tym, że nie unika rozgałęzienia logiki pobierania, a ponadto nie pozwala zachować deklaratywnej integralności referencyjnej. Bazy danych SQL nie mają możliwości zarządzania jedną kolumną klucza obcego dla jednej z wielu tabel nadrzędnych.Wspólne rozwiązanie domeny klucza podstawowego
Jednym ze sposobów, w jaki ludzie czasami radzą sobie z tym problemem, jest użycie pojedynczej puli identyfikatorów, aby nie było pomyłki dla dowolnego identyfikatora, niezależnie od tego, czy należy on do jednego podtypu, czy innego. Prawdopodobnie działałoby to całkiem naturalnie w scenariuszu bankowym, ponieważ nie zamierzasz wydawać tego samego numeru konta bankowego zarówno korporacji, jak i osobie fizycznej. Ma to tę zaletę, że pozwala uniknąć potrzeby atrybutu partycjonowania. Możesz to zrobić z tabelą supertypu lub bez niej. Korzystanie z tabeli typu super pozwala na stosowanie ograniczeń deklaratywnych w celu wymuszenia unikatowości. W przeciwnym razie musiałoby to być egzekwowane proceduralnie. To rozwiązanie jest znormalizowane, ale nie pozwoli ci zachować deklaratywnej integralności referencyjnej, chyba że utrzymasz tabelę supertypu. Nadal nic nie robi, aby uniknąć złożonej logiki pobierania.
Widać zatem, że tak naprawdę nie jest możliwe stworzenie przejrzystego projektu zgodnego ze wszystkimi zasadami, a jednocześnie prostego pobierania danych. Musisz zdecydować, gdzie będą twoje kompromisy.
źródło
corporation_id
iperson_id
wtedy można zasadniczo mamy rozwiązanie sub-pisania, poza tym, że stół super typ byłby podział na dwie, a klucz obcy zostaną odwrócone, więc ludzie nie mogą posiadać wiele kont. Ten rodzaj pokonuje cel.RefID
iRefTable
gdzieRefTable
jest ustalonym identyfikatorem identyfikującym tabelę docelową. Istnieje wiele przypadków użycia tego typu klucza i zbyt wiele, aby utrzymać 10 lub więcej tabel asocjacji / podtypów w celu wymuszenia integralności. Dla tych przypadkówkey
sam to stworzyłem .