Prosty przykład: istnieje tabela klientów.
create table Customers (
id integer,
constraint CustomersPK primary key (id)
)
Wszystkie inne dane w bazie danych powinny zawierać linki do Customer
, więc np. Orders
Wygląda to tak:
create table Orders (
id integer,
customer integer,
constraint OrdersPK primary key (customer, id),
constraint OrdersFKCustomers foreign key (customer) references Customers (id)
)
Załóżmy, że teraz istnieje tabela prowadząca do Orders
:
create table Items (
id integer,
customer integer,
order integer,
constraint ItemsPK primary key (customer, id),
constraint ItemsFKOrders foreign key (customer, order) references Orders (customer, id)
)
Czy powinienem dodać osobny klucz obcy od Items
do Customers
?
...
constraint ItemsFKCustomers foreign key (customer) references Customers (id)
Zamiast tego obraz: czy powinienem dodać linię przerywaną / FK?
Edycja: Dodałem definicje klucza podstawowego do tabel. Chciałbym powtórzyć powyższy punkt: baza danych jest zasadniczo wyciszana przez klientów, jako środek poprawności / bezpieczeństwa. Dlatego wszystkie klucze podstawowe zawierają customer
identyfikator.
database-design
foreign-key
vektor
źródło
źródło
Odpowiedzi:
Myślę, że to jest oryginalny pomysł.
Pierwszą rzeczą, na którą należy zwrócić uwagę, jest fakt, że PK w tabeli LineItem ma trzy atrybuty
{CustomerID, CustomerOrderNo, OdrerItemNo}
, a nie tylko dwa w twoim przykładzie.Drugą rzeczą do odnotowania jest zamieszanie wynikające z użycia
id
nazwy ogólnej dla atrybutu.CustomerOrderNo
Powinien być idealnie (1,2,3 ..) dla każdego klienta iOrderItemNo
(1,2,3 ...) dla każdego zamówienia.Cóż, jest to miłe, jeśli to możliwe, ale wymaga zapytania szukającego poprzedniej maksymalnej wartości, na przykład
co często nie jest preferowane w środowiskach o dużej liczbie transakcji, więc często zdarza się, że zastępuje się je automatycznym przyrostem, co zasadniczo służy temu samemu celowi. To prawda, że ten auto-incremet jest teraz unikalny, dlatego może być używany jako KLUCZ - ale możesz zdecydować się na to, by spojrzeć na to jako konieczny kompromis dla
OrderItemNo
.Tak więc po zmianie nazwy
CustomerOrderNo -> OrderNo
iOrderItemNo
->ItemNo
możesz dotrzeć do tego modeluWięc teraz, jeśli spojrzysz na
Order
poniższe, są wyjątkoweZauważ, że
{CustomerID, OrderNo}
jest propagowany do,LineItem
aby służył jako FK.Jeśli trochę
PKs {ItemNo} and {OrderNo}
zmrużysz oczy, jest to bliskie twojemu przykładowi, ale tylko z - w przeciwieństwie do dwóch kolumn PK z twojego przykładu.Teraz pytanie brzmi: dlaczego nie uprościć czegoś takiego?
Co jest w porządku, ale wprowadza PATH ZALEŻNOŚĆ - nie można przyłączyć
LineItem
sięCustomer
bezpośrednio, należy użyćOrder
w sprzężeniu.Jeśli to możliwe, wolę pierwszy przypadek - wybierasz swój ulubiony. I oczywiście nie ma potrzeby bezpośredniego FK od
LineItem
doCustomer
w tych trzech przypadkach.źródło
„Produkt” nie powinien bezpośrednio odwoływać się do „klienta”, ponieważ wynika to z „zamówienia” produktu. Tak więc kolumny „klient” nie będą w ogóle potrzebne.
Stosunek towaru do klienta jest zapewniony za pomocą istniejącego klucza obcego.
Jeśli order.id jest kolumną tożsamości, rozważ usunięcie item.customer razem.
źródło
customer
we wszystkich tabelach (a więc silosowanie DB) jest niezwykłym podejściem. Muszę wyznać, że to coś, co widziałem w mojej poprzedniej pracy. Czy to ma dla ciebie jakiś sens? Czy widziałeś już taki projekt?