MSSQL:如何通过引用同一个表来实现多个级联

问题描述 投票:2回答:2

也许是一个复杂的情况,但这是我的模型的简化版本:

情况:

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。

sql-server database-trigger cascading-deletes
2个回答
1
投票

通过创建一个首先删除子级表记录的触发器,然后在使用而不是删除后自动触发子触发器,就像以正确顺序执行的级联模式一样。

这通过添加更多逻辑解决了级联问题。此外,您可能需要使用主键而不是ID,以便在更大的键上进行正确的记录选择。

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
投票

MSSQL不支持多路径级联删除。

Foreign key constraint may cause cycles or multiple cascade paths?

它在其他DBMS中得到支持,比如PostgreSQL。

© www.soinside.com 2019 - 2024. All rights reserved.