SQL Server Введение ограничения FOREIGN KEY может привести к циклам или нескольким каскадным путям - PullRequest
0 голосов
/ 05 июня 2019

У меня есть две таблицы: T_User and T_Order

T_User
--------
ID
Name

T_Order имеет внешние ключи для T_User

T_Order
--------
ID
FK_UserActionOwnerID
FK_UserActionReceiverID

Тогда я сделал два отношения на моей диаграмме от T_User ID до обоих FK в T_Order. Я также установил для обоих отношений от delete and update rules до cascade, потому что я хочу, если запись T_User будет удалена, поэтому записи в T_Order должны быть удалены, или если T_User ID изменится, то также обновите его в T_Order. Тем не менее я получаю следующую ошибку:

Таблица 'T_User' успешно сохранена Таблица 'T_Order' - Невозможно создать отношение 'FK_T_Order_T_Users1'. Введение ограничения FOREIGN KEY 'FK_T_Order_T_Users1' в таблицу 'T_Order' может вызвать циклы или несколько каскадных путей. Укажите НА УДАЛИТЬ НЕТ ДЕЙСТВИЙ или ОБНОВЛЕНИЕ НЕТ ДЕЙСТВИЯ, или измените другие ограничения ИНОСТРАННОГО КЛЮЧА. Мог не создавать ограничение или индекс. Смотрите предыдущие ошибки.

Реальная диаграмма: нажмите здесь

1 Ответ

1 голос
/ 05 июня 2019

Ограничение внешнего ключа может вызывать циклы или множественные каскадные пути? Вопрос, связанный с @ Martin-Brown, предлагает использовать триггеры вместо каскадных внешних ключей.Вот пример использования триггера INSTEAD OF DELETE для того, что (я думаю) вы хотите сделать.

-- Create tables
create table dbo.T_User (
    ID int identity not null primary key,
    Name varchar(100) not null
)

create table dbo.T_Order (
    ID int identity not null primary key,
    FK_UserActionOwnerID int not null,
    FK_UserActionReceiverID int not null
)
go

-- Create foreign keys
alter table dbo.T_Order add constraint FK_T_Order_T_Users1 FOREIGN KEY (FK_UserActionOwnerID) REFERENCES dbo.T_User (ID) 
alter table dbo.T_Order add constraint FK_T_Order_T_Users2 FOREIGN KEY (FK_UserActionReceiverID) REFERENCES dbo.T_User (ID) 
go

-- Create trigger
create trigger tr_T_User_Delete on dbo.T_User instead of delete as
begin

    if (@@rowcount = 0) return

    delete o from dbo.T_Order o inner join deleted d on d.ID = o.FK_UserActionOwnerID

    delete o from dbo.T_Order o inner join deleted d on d.ID = o.FK_UserActionReceiverID

    delete u from dbo.T_User u inner join deleted d on d.ID = u.ID  

end
go

-- Demo
insert dbo.T_User (Name) values ('Peter'), ('Paul') -- Assume identity ID 1 and 2

insert dbo.T_Order (FK_UserActionOwnerID, FK_UserActionReceiverID) values (1, 1), (1, 2), (2, 2)

select * from dbo.T_Order

delete from dbo.T_User where ID = 1

select * from dbo.T_Order

Вы можете использовать триггеры INSTEAD OF UPDATE таким же образом, но вы можете подуматьо том, имеет ли смысл обновлять идентификаторы - обычно я этого не ожидаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...