Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Как можете да представите наследството в база данни?

@Bill Karwin описва три модела на наследяване в книгата си SQL Antipatterns, когато предлага решения за антимодел на SQL Entity-Attribute-Value. Това е кратък преглед:

Наследяване на единична таблица (известно още като наследяване на таблица на йерархия):

Използването на една таблица, както в първата ви опция, е може би най-простият дизайн. Както споменахте, много атрибути, които са специфични за подтип, ще трябва да получат NULL стойност на редове, където тези атрибути не се прилагат. С този модел ще имате една таблица с правила, която ще изглежда така:

+------+---------------------+----------+----------------+------------------+
| 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 -----/

Поддържането на простия дизайн е плюс, но основните проблеми с този подход са следните:

  • Когато става въпрос за добавяне на нови подтипове, ще трябва да промените таблицата, за да побере атрибутите, които описват тези нови обекти. Това може бързо да стане проблематично, когато имате много подтипове или ако планирате да добавяте подтипове редовно.

  • Базата данни няма да може да наложи кои атрибути се прилагат и кои не, тъй като няма метаданни, които да определят кои атрибути принадлежат към кои подтипове.

  • Също така не можете да наложите NOT NULL върху атрибути на подтип, които трябва да са задължителни. Ще трябва да се справите с това във вашето приложение, което като цяло не е идеално.

Наследяване на конкретна таблица:

Друг подход за справяне с наследяването е да се създаде нова таблица за всеки подтип, повтаряща всички общи атрибути във всяка таблица. Например:

--// 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    |   
+------+---------------------+------------------+

Този дизайн основно ще реши проблемите, идентифицирани за метода с единична таблица:

  • Задължителните атрибути вече могат да бъдат наложени с NOT NULL .

  • Добавянето на нов подтип изисква добавяне на нова таблица вместо добавяне на колони към съществуваща.

  • Също така няма риск да бъде зададен неподходящ атрибут за конкретен подтип, като например vehicle_reg_no поле за политика за собственост.

  • Няма нужда от type атрибут, както в метода на единична таблица. Типът вече е дефиниран от метаданните:името на таблицата.

Този модел обаче има и няколко недостатъка:

  • Общите атрибути се смесват със специфичните за подтип атрибути и няма лесен начин да ги идентифицирате. Базата данни също няма да знае.

  • Когато дефинирате таблиците, ще трябва да повторите общите атрибути за всеки подтип таблица. Това определено не е СУХО.

  • Търсенето на всички правила, независимо от подтипа, става трудно и ще изисква куп UNION с.

Ето как ще трябва да потърсите всички правила, независимо от типа:

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;

Обърнете внимание как добавянето на нови подтипове ще изисква горната заявка да бъде променена с допълнителен UNION ALL за всеки подтип. Това лесно може да доведе до грешки във вашето приложение, ако тази операция бъде забравена.

Наследяване на таблица на класове (известно още като наследяване на таблица по тип):

Това е решението, което @David споменава в другия отговор. Вие създавате една таблица за вашия базов клас, която включва всички общи атрибути. След това ще създадете специфични таблици за всеки подтип, чийто първичен ключ също служи като външен ключ към базовата таблица. Пример:

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)
);

Това решение решава проблемите, идентифицирани в другите два дизайна:

  • Задължителните атрибути могат да бъдат наложени с NOT NULL .

  • Добавянето на нов подтип изисква добавяне на нова таблица вместо добавяне на колони към съществуваща.

  • Няма риск да бъде зададен неподходящ атрибут за конкретен подтип.

  • Няма нужда от type атрибут.

  • Вече общите атрибути не се смесват със специфичните за подтип атрибути.

  • Най-накрая можем да останем СУХИ. Не е необходимо да се повтарят общите атрибути за всеки подтип таблица при създаването на таблиците.

  • Управление на автоматично нарастващ id за политиките става по-лесно, тъй като това може да се обработва от основната таблица, вместо всяка таблица на подтип да ги генерира независимо.

  • Търсенето на всички правила, независимо от подтипа, сега става много лесно:Без UNION е необходимо - само SELECT * FROM policies .

Смятам, че подходът на таблицата с класове е най-подходящ в повечето ситуации.

Имената на тези три модела идват от книгата на Мартин Фаулър Модели на архитектурата на корпоративните приложения.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Търсене на текст в съхранена процедура в SQL Server

  2. Групи за наличност на SQL Server AlwaysOn:Инсталация и конфигурация, част 2

  3. SQL Server Log Shipping &Disaster Recovery Installation and Configuration -1

  4. Получаване на максимална стойност от редове и присъединяване към друга таблица

  5. Как да се свържа с база данни MSSQL с помощта на DBI модула на Perl в Windows?