MSSQL:如何引用相同的多个级联 table
MSSQL: how to have multiple cascades with referencing the same table
可能情况比较复杂,但这是我模型的简化版本:
情况:
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'.
问题
如何才能从 table3
中删除一条记录?如您所见,我已经尝试使用触发器 FOR DELETE
,但这会导致 FK 约束错误(因此 FOR DELETE
实际上是 AFTER DELETE
)。
我也尝试过使用 INSTEAD DELETE
但这不能使用,因为父级 (table2
) 也有一个 ON DELETE CASCADE。
MSSQL 不支持多路径级联删除。
Foreign key constraint may cause cycles or multiple cascade paths?
它在其他 DBMS 中受支持,例如 PostgreSQL。
通过创建一个触发器,它首先删除子级别 table 记录,然后在使用而不是删除之后删除自身,您可以像按正确顺序执行的级联模式一样触发子触发器。
这通过添加更多逻辑解决了级联问题。此外,您可能希望在此处使用主键而不是 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
可能情况比较复杂,但这是我模型的简化版本:
情况:
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'.
问题
如何才能从 table3
中删除一条记录?如您所见,我已经尝试使用触发器 FOR DELETE
,但这会导致 FK 约束错误(因此 FOR DELETE
实际上是 AFTER DELETE
)。
我也尝试过使用 INSTEAD DELETE
但这不能使用,因为父级 (table2
) 也有一个 ON DELETE CASCADE。
MSSQL 不支持多路径级联删除。
Foreign key constraint may cause cycles or multiple cascade paths?
它在其他 DBMS 中受支持,例如 PostgreSQL。
通过创建一个触发器,它首先删除子级别 table 记录,然后在使用而不是删除之后删除自身,您可以像按正确顺序执行的级联模式一样触发子触发器。
这通过添加更多逻辑解决了级联问题。此外,您可能希望在此处使用主键而不是 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