2015-01-26 3 views
0

Допустим, у меня есть 4 таблицы, A, B, C, D.Перекрытие внешних ключей и каскада при удалении

A имеет первичный ключ ID.
B имеет первичный ключ (ID, A.ID), где A.ID является внешним ключом с CASCADE ON DELETE.
C имеет первичный ключ (ID, A.ID), где A.ID является внешним ключом с CASCADE ON DELETE.
D имеет первичный ключ (ID, A.ID, B.ID, C.ID), с (A.ID, B.ID) и (A.ID, C.ID) - внешние ключи.

Есть ли способ КАСКАДА ПО УДАЛЕНИЮ для обоих внешних ключей D? Пытаться каскадом для обоих внешних ключей дает мне «несколько каскадных путей» для сбоев как для внешних ключей, так и для каскадных удалений A.ID, но мне нужно удалить строку из D, если строка B.ID или C.ID будет удалена.

EDIT:

Столы DeviceTypes, DeviceInstances, DeviceDataElements, DeviceDataRecords

DeviceTypes имеет первичный ключ ID.

Устройства DeviceInstances имеет первичный ключ (ID, DeviceTypes.ID) с DeviceTypes.ID, являющийся внешним ключом с CASCADE ON DELETE.

У DeviceDataElements есть первичный ключ (ID, DeviceTypes.ID) с DeviceTypes.ID, являющийся внешним ключом с CASCADE ON DELETE.

D имеет первичный ключ (ID, Devices.ID, DeviceElements.ID, DeviceInstances.ID), с (DeviceTypes.ID, DeviceElements.ID) и (DeviceTypes.ID, DeviceInstances.ID), являющимися внешними ключами.

i.E DeviceRecord содержит точку данных для DeviceDataElement определенного DeviceInstance.

+0

звучит беспорядочно для меня, можете ли вы предоставить некоторые простые данные и сценарии, чтобы прояснить структуру таблицы. – Tanner

+0

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

+0

@Tanner Дала все имена, чтобы придать ситуации еще больший контекст. – Mike

ответ

0

Я могу только догадываться о предметной области, но что касается меня, DeviceTypes.ID не должен быть частью первичного ключа в DeviceInstances и DeviceDataElements. Например, этот столбец не требуется для уникальной идентификации записи в DeviceInstances. Невозможно иметь DeviceInstance с тем же DeviceInstanceID, но с другим DeviceTypeID.

Также я не думаю, что удаление из DeviceTypes должно быть каскадным. Это не обычная (и опасная) операция для удаления из DeviceType. Если вам нужно его реализовать, напишите хранимую процедуру и удалите из соответствующих таблиц в правильном порядке (DeviceDataRecords, DeviceDataElements, DeviceInstances, DeviceTypes). Другой способ реализовать это - пометить DeviceType как удаленный, а не физически удалить. В этом случае вы никогда не потеряли бы свои данные.

Точно так же удаляются из DeviceDataElements. Я не думаю, что DataElements когда-нибудь изменится для некоторого типа.

В этом дизайне вам нужно управлять со стороны приложения, чтобы DeviceRecord содержал только типы данных, разрешенные типом экземпляра. Это очень распространенный и естественный способ справиться с этой ситуацией (сделать это на стороне приложения или бизнес-логики). С логической точки зрения DeviceDataRecords содержит тот факт, что у Some Instance есть некоторый DataElement (некоторого значения). Непросто проверять типы в этой таблице. Нецелесообразно делегировать эти проверки SQL Server. В случае, если на стороне сервера есть только доступная опция, вы можете рассмотреть триггеры для этой задачи, поэтому на INSERT в Records вы можете проверить это правило (это тоже не очень хороший вариант).

Я могу ошибаться в предметной области вашего приложения, поэтому, пожалуйста, исправьте меня или добавьте новую информацию.

CREATE TABLE DeviceTypes(DeviceTypeID int not null identity primary key); 
go 

CREATE TABLE DeviceInstances (DeviceInstanceID int not null identity primary key, DeviceTypeID int not null) 
ALTER TABLE DeviceInstances ADD CONSTRAINT FK_DeviceInstances_DeviceTypes FOREIGN KEY (DeviceTypeID) REFERENCES DeviceTypes(DeviceTypeID) 
go 

CREATE TABLE DeviceDataElements (DeviceDataElementID int not null identity primary key, DeviceTypeID int not null) 
ALTER TABLE DeviceDataElements ADD CONSTRAINT FK_DeviceDataElements_DeviceTypes FOREIGN KEY (DeviceTypeID) REFERENCES DeviceTypes(DeviceTypeID) 
go 

CREATE TABLE DeviceDataRecords (RecordID int not null identity primary key, DeviceInstanceID int not null, DeviceDataElementID int not null) 
ALTER TABLE DeviceDataRecords ADD CONSTRAINT FK_DeviceDataRecords_DeviceInstances FOREIGN KEY (DeviceInstanceID) REFERENCES DeviceInstances(DeviceInstanceID) on delete cascade 
ALTER TABLE DeviceDataRecords ADD CONSTRAINT FK_DeviceDataRecords_DeviceDataElements FOREIGN KEY (DeviceDataElementID) REFERENCES DeviceDataElements(DeviceDataElementID) on delete cascade 
Смежные вопросы