Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Jak możesz reprezentować dziedziczenie w bazie danych?

@Bill Karwin opisuje trzy modele dziedziczenia w swojej książce o Antywzorcach SQL, proponując rozwiązania dotyczące antywzorca SQL Entity-Attribute-Value. Oto krótki przegląd:

Dziedziczenie pojedynczej tabeli (inaczej dziedziczenie tabeli na hierarchię):

Korzystanie z jednej tabeli, jak w pierwszej opcji, jest prawdopodobnie najprostszym projektem. Jak wspomniałeś, wiele atrybutów, które są specyficzne dla podtypu, będzie musiało otrzymać NULL wartość w wierszach, w których te atrybuty nie mają zastosowania. W tym modelu miałbyś jedną tabelę polityk, która wyglądałaby mniej więcej tak:

+------+---------------------+----------+----------------+------------------+
| id   | date_issued         | type     | vehicle_reg_no | property_address |
+------+---------------------+----------+----------------+------------------+
|    1 | 2010-08-20 12:00:00 | MOTOR    | 01-A-04004     | NULL             |
|    2 | 2010-08-20 13:00:00 | MOTOR    | 02-B-01010     | NULL             |
|    3 | 2010-08-20 14:00:00 | PROPERTY | NULL           | Oxford Street    |
|    4 | 2010-08-20 15:00:00 | MOTOR    | 03-C-02020     | NULL             |
+------+---------------------+----------+----------------+------------------+

\------ COMMON FIELDS -------/          \----- SUBTYPE SPECIFIC FIELDS -----/

Prosty projekt to plus, ale główne problemy związane z tym podejściem są następujące:

  • Jeśli chodzi o dodawanie nowych podtypów, musiałbyś zmienić tabelę, aby pomieścić atrybuty opisujące te nowe obiekty. Może to szybko stać się problematyczne, gdy masz wiele podtypów lub jeśli planujesz regularnie dodawać podtypy.

  • Baza danych nie będzie w stanie wymusić, które atrybuty mają zastosowanie, a które nie, ponieważ nie ma metadanych określających, które atrybuty należą do których podtypów.

  • Nie możesz również wymusić NOT NULL na atrybutach podtypu, które powinny być obowiązkowe. Musiałbyś sobie z tym poradzić w swojej aplikacji, co generalnie nie jest idealne.

Dziedziczenie stołu betonowego:

Innym podejściem do rozwiązania problemu dziedziczenia jest utworzenie nowej tabeli dla każdego podtypu, powtarzając wszystkie wspólne atrybuty w każdej tabeli. Na przykład:

--// Table: policies_motor
+------+---------------------+----------------+
| id   | date_issued         | vehicle_reg_no |
+------+---------------------+----------------+
|    1 | 2010-08-20 12:00:00 | 01-A-04004     |
|    2 | 2010-08-20 13:00:00 | 02-B-01010     |
|    3 | 2010-08-20 15:00:00 | 03-C-02020     |
+------+---------------------+----------------+
                          
--// Table: policies_property    
+------+---------------------+------------------+
| id   | date_issued         | property_address |
+------+---------------------+------------------+
|    1 | 2010-08-20 14:00:00 | Oxford Street    |   
+------+---------------------+------------------+

Ten projekt zasadniczo rozwiąże problemy zidentyfikowane dla metody pojedynczej tabeli:

  • Obowiązkowe atrybuty można teraz wymuszać za pomocą NOT NULL .

  • Dodanie nowego podtypu wymaga dodania nowej tabeli zamiast dodawania kolumn do już istniejącej.

  • Nie ma również ryzyka, że ​​dla określonego podtypu zostanie ustawiony niewłaściwy atrybut, taki jak vehicle_reg_no pole dla polityki nieruchomości.

  • Nie ma potrzeby stosowania type atrybut jak w metodzie pojedynczej tabeli. Typ jest teraz zdefiniowany przez metadane:nazwę tabeli.

Jednak ten model ma również kilka wad:

  • Atrybuty wspólne są mieszane z atrybutami specyficznymi dla podtypu i nie ma łatwego sposobu ich identyfikacji. Baza danych również nie będzie wiedziała.

  • Definiując tabele, musiałbyś powtórzyć wspólne atrybuty dla każdej tabeli podtypów. To zdecydowanie nie jest SUCHE.

  • Wyszukiwanie wszystkich zasad niezależnie od podtypu staje się trudne i wymagałoby wielu UNION s.

W ten sposób musiałbyś zapytać o wszystkie zasady, niezależnie od ich typu:

SELECT     date_issued, other_common_fields, 'MOTOR' AS type
FROM       policies_motor
UNION ALL
SELECT     date_issued, other_common_fields, 'PROPERTY' AS type
FROM       policies_property;

Zwróć uwagę, że dodanie nowych podtypów wymagałoby zmodyfikowania powyższego zapytania za pomocą dodatkowego UNION ALL dla każdego podtypu. Może to łatwo prowadzić do błędów w Twojej aplikacji, jeśli ta operacja zostanie zapomniana.

Dziedziczenie tabeli klas (inaczej dziedziczenie tabeli według typu):

To jest rozwiązanie, o którym @David wspomina w drugiej odpowiedzi. Tworzysz pojedynczą tabelę dla swojej klasy bazowej, która zawiera wszystkie typowe atrybuty. Następnie utworzysz określone tabele dla każdego podtypu, którego klucz podstawowy służy również jako klucz obcy do tabeli podstawowej. Przykład:

CREATE TABLE policies (
   policy_id          int,
   date_issued        datetime,

   -- // other common attributes ...
);

CREATE TABLE policy_motor (
    policy_id         int,
    vehicle_reg_no    varchar(20),

   -- // other attributes specific to motor insurance ...

   FOREIGN KEY (policy_id) REFERENCES policies (policy_id)
);

CREATE TABLE policy_property (
    policy_id         int,
    property_address  varchar(20),

   -- // other attributes specific to property insurance ...

   FOREIGN KEY (policy_id) REFERENCES policies (policy_id)
);

To rozwiązanie rozwiązuje problemy zidentyfikowane w pozostałych dwóch projektach:

  • Atrybuty obowiązkowe można wymusić za pomocą NOT NULL .

  • Dodanie nowego podtypu wymaga dodania nowej tabeli zamiast dodawania kolumn do już istniejącej.

  • Nie ma ryzyka, że ​​dla określonego podtypu zostanie ustawiony niewłaściwy atrybut.

  • Nie ma potrzeby stosowania type atrybut.

  • Teraz wspólne atrybuty nie są już mieszane z atrybutami specyficznymi dla podtypu.

  • W końcu możemy pozostać SUCHYM. Nie ma potrzeby powtarzania wspólnych atrybutów dla każdej tabeli podtypów podczas tworzenia tabel.

  • Zarządzanie automatycznym przyrostem id dla polityk staje się łatwiejsze, ponieważ może to być obsługiwane przez tabelę bazową, zamiast przez każdą tabelę podtypów generującą je niezależnie.

  • Wyszukiwanie wszystkich zasad niezależnie od podtypu staje się teraz bardzo łatwe:Brak UNION s potrzebne - wystarczy SELECT * FROM policies .

Uważam, że podejście oparte na stole klasowym jest najbardziej odpowiednie w większości sytuacji.

Nazwy tych trzech modeli pochodzą z książki Martina Fowlera Wzorce architektury aplikacji korporacyjnych.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Odniesienie do aliasu kolumny w klauzuli WHERE

  2. OPENJSON „Nieprawidłowa składnia w pobliżu słowa kluczowego „z”.”. w SQL Server (ROZWIĄZANE)

  3. Dlaczego SQL Server zaokrągla wyniki dzielenia dwóch liczb całkowitych?

  4. Wybór procesora dla SQL Server 2012

  5. Czy w Microsoft SQL Server istnieje typ danych logicznych, taki jak w MySQL?