MSSQL: как иметь несколько каскадов со ссылкой на одну и ту же таблицу - PullRequest
0 голосов
/ 21 февраля 2019

Может быть, сложная ситуация, но это упрощенная версия моей модели:

Ситуация:

drop table table4
drop table table2
drop table table3
drop table table1
drop table table0

create table table0 (
    id integer not null primary key
)

create table table1 (
    id integer not null primary key
)

create table table2 (
    id integer not null primary key,
    table0_id integer not null,
    table1_id integer not null
)

create table table3 (
    id integer not null primary key,
    table1_id integer not null
)

create table table4 (
    id integer not null primary key,
    table2_id integer not null,
    table3_id integer not null
)

alter table table2 add constraint fk_table2_table0 foreign key (table0_id)
references table0 (id) on delete cascade on update no action

alter table table2 add constraint fk_table2_table1 foreign key (table1_id)
references table1 (id) on delete cascade on update no action

alter table table3 add constraint fk_table3_table1 foreign key (table1_id)
references table1(id) on delete cascade on update no action

alter table table4 add constraint fk_table4_table2 foreign key (table2_id)
references table2(id) on delete cascade on update no action

alter table table4 add constraint fk_table4_table3 foreign key (table3_id)
references table3(id) on delete no action on update no action

GO
CREATE TRIGGER WhenRowFromTable3IsDeleted ON table3
    FOR DELETE       
AS
BEGIN
    DELETE FROM table4 WHERE table3_id = (SELECT id FROM DELETED)
END
GO

INSERT INTO table0 (id) VALUES (1)
INSERT INTO table1 (id) VALUES (1)
INSERT INTO table2 (id, table0_id, table1_id) VALUES (1, 1, 1)
INSERT INTO table3 (id, table1_id) VALUES (1, 1)
INSERT INTO table4 (id, table2_id, table3_id) VALUES (1,1,1)

DELETE FROM table3 WHERE id = 1

SELECT * FROM table1, table0

Результат: The DELETE statement conflicted with the REFERENCE constraint "fk_table4_table3". The conflict occurred in database "testing", table "dbo.table4", column 'table3_id'.

enter image description here

Вопрос

Как сделать возможным удаление записи из table3?Я пробовал это с триггером FOR DELETE, как вы можете видеть, но это приводит к ошибке ограничения FK (так что FOR DELETE на самом деле AFTER DELETE).Я также попытался использовать INSTEAD DELETE, но это нельзя использовать, потому что родитель (table2) также получил ON DELETE CASCADE.

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

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

Это решаетвопрос каскада, добавив немного больше логики.Также вы можете использовать первичный ключ вместо идентификатора здесь для правильного выбора записи на клавишах большего размера.

drop table table4

drop table table2

drop table table3

drop table table1

drop table table0



create table table0 (

   id integer not null primary key

)



create table table1 (

   id integer not null primary key

)



create table table2 (

   id integer not null primary key,

   table0_id integer not null,

   table1_id integer not null

)



create table table3 (

   id integer not null primary key,

   table1_id integer not null

)



create table table4 (

   id integer not null primary key,

   table2_id integer not null,

   table3_id integer not null

)



alter table table2 add constraint fk_table2_table0 foreign key (table0_id)

references table0 (id) on delete cascade on update no action



alter table table2 add constraint fk_table2_table1 foreign key (table1_id)

references table1 (id) on delete cascade on update no action



alter table table3 add constraint fk_table3_table1 foreign key (table1_id)

references table1(id) on delete no action on update no action



alter table table4 add constraint fk_table4_table2 foreign key (table2_id)

references table2(id) on delete cascade on update no action



alter table table4 add constraint fk_table4_table3 foreign key (table3_id)

references table3(id) on delete no action on update no action



GO

CREATE TRIGGER WhenRowFromTable3IsDeleted ON table3

   INSTEAD OF DELETE      

AS

BEGIN

   DELETE FROM table4 WHERE table3_id = (SELECT id FROM DELETED)

    DELETE FROM table3 WHERE id = (SELECT id FROM DELETED)

END

GO

CREATE TRIGGER WhenRowFromTable1IsDeleted ON table1

   INSTEAD OF DELETE      

AS

BEGIN

   DELETE FROM table3 WHERE table1_id = (SELECT id FROM DELETED)

    DELETE FROM table1 WHERE id = (SELECT id FROM DELETED)

END

GO



INSERT INTO table0 (id) VALUES (1)

INSERT INTO table1 (id) VALUES (1)

INSERT INTO table2 (id, table0_id, table1_id) VALUES (1, 1, 1)

INSERT INTO table3 (id, table1_id) VALUES (1, 1)

INSERT INTO table4 (id, table2_id, table3_id) VALUES (1,1,1)



DELETE FROM table3 WHERE id = 1



SELECT * FROM table1, table0
0 голосов
/ 21 февраля 2019

Многолучевое каскадное удаление не поддерживается MSSQL.

Ограничение внешнего ключа может вызывать циклы или несколько каскадных путей?

Поддерживается в других СУБД, таких как PostgreSQL.

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