Czy uznanie za niewłaściwą praktykę jest posiadanie wielu zerowalnych FK na stole w SQL Server

13

W mojej strukturze bazy danych w SQL Server mam 3 rodzaje produktów, które wymagają różnych informacji o zamówieniu. Więc stworzyłem jeden Customersstół i trzy różne zlecenia tabele: OrdersForProductAs, OrdersForProductBs, OrdersForProductCs. Tabela wszystkich zamówień ma relację jeden do wielu na Customersstole.

Mam też inny stolik, w którym są Paymentsi będą przechowywane szczegóły płatności. Mam jednak wątpliwości, jak to ustrukturyzować.

Ponieważ mam wiele rodzajów produktów, a klient może mieć zamówienia na wiele produktów jednocześnie, muszę powiązać te trzy tabele zamówień z tabelami Payments.

Inną kwestią jest to, że klient może mieć zamówienie tylko na jeden rodzaj produktu. Tak więc kolumny FK w Paymentstabeli muszą być nullable.

Moje pytanie brzmi, czy te nullablekolumny FK byłyby dla mnie problemem na dłuższą metę, czy nie? Ogólnie rzecz biorąc, czy uznanie za zerowe kolumny FK na stole byłoby uważane za złą praktykę?

tugberk
źródło
2
Pamiętaj, aby dołączyć ograniczenie sprawdzania, aby co najmniej jeden z tych FK nie był zerowy.
Damien_The_Unbeliever
3
Jeden zerowy klucz obcy to jeden za dużo.
nvogel,

Odpowiedzi:

13

Chciałbym zapytać, dlaczego OrdersForProductXw ogóle masz stoły
. Możliwe, że problem FK, o który prosiłeś, można zaprojektować ...

Jeśli te tabele mają tę samą strukturę, wystarczy po prostu ProductTypekolumna w OrderProducttabeli. Następnie Paymentwystarczy połączyć z tym jednym FK

Jeśli tabela ma różne struktury, zakładam, że mają pewne wspólne atrybuty. Możesz więc mieć wspólny OrderProductstół, a następnie określony stół podrzędny dla każdego rodzaju produktu (patrz poniżej) Ponownie, Paymentpo prostu linki do wspólnej tabeli z jednym FK

Jest to „wzorzec klucza / podtypu”

  • UQ1 to „superklucz” używany w kluczu obcym w tabelach podtypów
  • Każda tabela podtypów ma złożone PK i FK (OrderID, ProductType)
  • Każda tabela podtypów ma ograniczenie SPRAWDŹ, aby ograniczyć typy w tej tabeli

Zamów produkt

  • OrderID, PK, UQ1
  • ProductType, UQ1
  • CommonThing1
  • ...

OrderProductA

  • OrderID, PK, FK
  • ProductType, PK, FK, CHECK ProductType = A
  • ProductAThing 1
  • ...

OrderProductB

  • OrderID, PK, FK
  • ProductType, PK, FK, CHECK ProductType = B
  • ProductBThing1
  • ...
gbn
źródło
4
@tugberk: Zauważ, że NULLprzy takim podejściu nie będziesz mieć żadnych kolumn FK.
ypercubeᵀᴹ
„Jeśli te tabele mają tę samą strukturę” , nie mają takiej samej struktury.
tugberk
5

Unikaj zerowalnych „kluczy obcych”. Mają wiele wad.

Ograniczenie w wierszu odniesienia nie zawsze jest egzekwowane, gdy klucz obcy zawiera wartość null. Jednak to domyślne zachowanie nie jest spójne między różnymi systemami DBMS. Niektóre DBMS obsługują opcje konfiguracji do zmiany zachowania dopuszczalnych kluczy obcych, a niektóre nie. Deweloperzy i użytkownicy SQL mogą więc nie wiedzieć, co tak naprawdę oznacza zerowe ograniczenie klucza obcego z punktu widzenia integralności danych. Przeniesienie bazy danych między produktami DBMS lub nawet między różnymi serwerami korzystającymi z tego samego produktu może dawać niespójne wyniki.

Narzędzia do projektowania baz danych, narzędzia integracyjne i inne oprogramowanie nie zawsze obsługują je poprawnie, a uzyskiwane wyniki mogą być nieprawidłowe.

Klucze obce są często używane w sprzężeniach i innej logice zapytań, co komplikuje problemy użytkownikom, którzy uważają, że ograniczenie obowiązuje, gdy go nie ma lub nie znają logiki stosowanej przez dany system DBMS.

Niektóre funkcje optymalizacji zapytań, które umożliwiają przepisywanie zapytań i inne optymalizacje, mogą być niedostępne, gdy klucz obcy ma wartość zerową.

Z logicznego punktu widzenia nullowalne ograniczenie „klucza obcego” nie ma większego logicznego sensu. Zgodnie ze standardem SQL takie ograniczenie nie może zostać naruszone, nawet jeśli tabela, do której następuje odwołanie, jest pusta. Jest to sprzeczne z jednym z najczęstszych domniemanych uzasadnień użycia wartości zerowej - że reprezentuje przypadek „nieznany”. Jeśli nie ma prawidłowych wartości X, to każdy „nieznany” X z pewnością nie może być prawidłową wartością - a jednak SQL na to zezwala.

Klucze obce dopuszczające wartości zerowe są całkowicie niepotrzebne. Zawsze możesz albo rozłożyć klucz obcy na nową tabelę, albo użyć wzorca nadtypu / podtypu, aby wartości zerowe nie były potrzebne. W trosce o prostotę i dokładność lepiej jest zatem pozostawić wartości zerowe niż je wstawić.

nvogel
źródło
2

Nigdy nie słyszałem, by stosowanie złych kolumn FK było uważane za złą praktykę. Idealnie pasują do kolumny, która odwołuje się do innej tabeli, ale może nie zostać wypełniona (tzn. Są to dane opcjonalne).

(Jak myślisz, dlaczego byłby to problem?)

StilesCrisis
źródło
Dzięki! Cóż, nie jestem do końca tego pewien, ale kilka lat temu miałem taki projekt i pamiętam, że coś boli mnie głowa . Więc nie jestem jasne, jak widzisz: dlaczego zadałem pytanie.