Условное отношение внешнего ключа

14

В настоящее время у меня есть внешний ключ между двумя сущностями, и я хотел бы сделать это отношение условным для entityType одной из таблиц. Вот иерархия таблиц, это делается с помощью FK-ссылок от дочернего элемента к родительскому.

                  Store
            /                \
  Employees                    \
                             TransactionalStores
                            /       |         \
                     Kiosks         |          BrickMortars
                                 Onlines

В настоящее время у меня есть отношение FK от сотрудника к магазину

ALTER TABLE Employees ADD CONSTRAINT Employee_Store
            FOREIGN KEY (TransStoreId)
            REFERENCES TransactionalStores(StoreId)

Я хотел бы добавить условное:

WHERE TransactionalStores.storeType != 'ONLINE_TYPE'

Это возможно или я должен разделить TransactionalStores на два новых подтипа (например, PhysicalStores и VirtualStores)

туз
источник
Связанный: dba.stackexchange.com/q/34040/3684 , dba.stackexchange.com/q/58970/3684
Эрвин Брандштеттер

Ответы:

17

Внешние ключи можно сделать условными ... вроде. Вы не показываете расположение каждой таблицы, поэтому вот типичный дизайн, показывающий ваши отношения:

create table TransactionalStores(
    ID        int   not null auto_increment,
    StoreType char  not null,
    ..., -- other data
    constraint CK_TransStoreType check( StoreType in( 'B', 'K', 'O' )),
    constraint PK_TransactionalStores primary key( ID ),
    constraint UQ_TransStoreTypes unique( ID, StoreType ) -- for FK references
);
create table Kiosks(
    ID         int   not null,
    StoreType  char  not null,
    ..., -- other Kiosk data
    constraint CK_KioskStoreType check( StoreType = 'K' ), -- kiosks only
    constraint PK_Kiosks primary key( ID, StoreType ),
    constraint FK_Kiosks_TransStores foreign key( ID, StoreType )
        references TransactionalStores( ID, StoreType )
);

Onlines и BrickMorters будут иметь одинаковую базовую структуру, но с StoreType, ограниченным только «O» или «B», в зависимости от ситуации.

Теперь вам нужна ссылка из другой таблицы на TransactionalStores (и через нее на различные таблицы магазинов), но ограниченная киосками и BrickMorter. Единственная разница будет в ограничении:

create table Employees(
    ID         int       not null,
    StoreID    int,
    StoreType  char,
    ..., -- other Employee data
    constraint PK_Employees primary key( ID ),
    constraint CK_Employees_StoreType check( coalesce( StoreType, 'X' ) <> 'O' )), -- Online not allowed
    constraint FK_Employees_TransStores foreign key( StoreID, StoreType )
        references TransactionalStores( ID, StoreType )
);

В этой таблице ссылка FK заставляет StoreType быть либо «K», «O» или «B», но ограничение поля дополнительно ограничивает его только «K» или «B».

Для иллюстрации я использовал проверочное ограничение, чтобы ограничить типы хранилищ в таблице TransactionStores. В реальной жизни, таблица поиска StoreTypes с StoreType, являющейся FK для этой таблицы, вероятно, была бы лучшим выбором дизайна.

TommCatt
источник
9

Внешний ключ нельзя сделать условным, так что об этом не может быть и речи. Бизнес-правило заключается в том, что сотрудник может работать в одном и только одном физическом магазине. Учитывая это, супер тип магазина имеет два подтипа, как вы предложили: физический и онлайн . Каждый физический магазин может быть укомплектован одним или несколькими сотрудниками, и каждый сотрудник должен быть назначен в один и только один физический магазин. Физические магазины тогда имеют два подтипа, Brick и Mortar и Kiosk . Имеет три прямых подтипа - киоск , онлайн , кирпич и миномет- скрывает свойство, которым обладает каждый магазин - независимо от того, находится оно в физическом месте или нет. Теперь дизайн полагается на человека, чтобы понять семантику, присущую именам подтипов, чтобы понять, что в интернет-магазинах нет сотрудников. Это не очевидно в заявленной схеме, и код в форме триггера должен быть написан, чтобы выразить это понимание способом, который может применять СУБД. Разработка, тестирование и поддержка триггера, который не влияет на производительность, является гораздо более сложным решением для реализации, как показано в книге « Прикладная математика для специалистов по базам данных» .

Подтипирование Store вначале по его типу местоположения, а затем по типу структуры физического хранилища представляет собой более правильный дизайн по отношению к бизнес-правилам и устраняет необходимость в написании кода для обеспечения соблюдения правила. Как только свойство явно включено в качестве типа местоположения магазина, которое можно использовать в качестве дискриминатора для подтипов, можно напрямую установить связь между сотрудниками и физическими хранилищами и, таким образом, полностью реализовать правило только с ограничением внешнего ключа. Это модель данных, созданная с помощью Oracle SQL Developer Data Modeler, которая показывает супер и субтипирование с использованием Barker-Ellis.box in box обозначение для супер и подтипов, которые я предпочитаю для его элегантного представления. Диаграмма теперь может также ясно показать правило.

введите описание изображения здесь

Тод эверетт
источник