我有一张桌子(让我们称之为tMainTable
),这张桌子目前被其他许多桌子引用(而且它们的数量可能随着时间的推移而增长)。
由于循环检测,其中一些表不能只有ON DELETE CASCADE
子句。
我知道如果我在ON DELETE CASCADE
上写INSTEAD OF
触发器,我可以删除tMainTable
子句。
但是,每当一个新表被添加为tMainTable
的后代时,就必须编辑触发器(作为“模块化”瘾君子)只是蹩脚(而且有风险 - 想象一个没有经验的用户只是打破了整个事情)。
所以我正在认真寻找另一种方法。
我只是想到了一些事情。
如果我创建一个表tMainTableID
,只保留ID
tMainTable
AFTER
的副本(使用INSTEAD OF
触发器进行插入的副本),该怎么办?
然后,我在tMainTable
上创建tMainTableID
触发器,首先删除tMainTable
的相应行,然后删除tMainTableID
的实际行。
如果我这样做,我应该有一些非常好用的东西:一个表(tMainTable
)我可以“附加”AFTER DELETE触发器来删除任何需要在行{{{{{{ 1}}实际上已删除。
-- Made by ME on 2014-01-27
CREATE TRIGGER tMainTableID_AFDEL_tTableChild01
AFTER DELETE
ON tMainTableID
AS
BEGIN
DELETE T
FROM deleted AS D
INNER JOIN tTableChild01 AS T ON (
T.RefToMainID = D.ID
)
END
GO
-- Made by ME on 2015-01-01
CREATE TRIGGER tMainTableID_AFDEL_tTableChild02
AFTER DELETE
ON tMainTableID
AS
BEGIN
DELETE T
FROM deleted AS D
INNER JOIN tTableChild02 AS T ON (
T.RefToMainID = D.ID
)
END
GO
-- Made by Iamun Kompetent on 2016-01-01
CREATE TRIGGER tMainTableID_AFDEL_tTableChild03
AFTER DELETE
ON tMainTableID
AS
BEGIN
DELETE T
FROM inserted AS D
INNER JOIN tTableChild02 AS T ON (
D.ID = D.ID
)
END
GO
你觉得这种方法有什么问题,甚至更好,你知道更好的方法来实现模块化吗?
- 编辑:简单的例子
create table tTest20140128 (
id int not null primary key
)
go
create table tTest20140128_Child01 (
id int not null primary key references tTest20140128(id) on delete no action
)
go
create table tTest20140128_Child02 (
id int not null primary key references tTest20140128(id) on delete no action
)
go
insert tTest20140128 values (1), (2), (3)
insert tTest20140128_Child01 values (1), (2), (3)
insert tTest20140128_Child02 values (1), (2), (3)
go
delete from tTest20140128 -- Error
go
-- table for holding copies of ids
create table tTest20140128_ID (
id int not null primary key references tTest20140128(id) on delete no action
)
go
insert tTest20140128_ID
select id from tTest20140128
go
-- trigger that keeps tTest20140128_ID up to date for new ids
create trigger tTest20140128_AFINS
on tTest20140128
after insert
as
begin
insert tTest20140128_ID
select id from inserted
end
go
-- Instead of delete (keeps tTest20140128_ID up to date for deleted ids)
create trigger tTest20140128_IODEL
on tTest20140128
instead of delete
as
begin
delete ID
from deleted AS D
inner join tTest20140128_ID AS ID ON (
ID.id = D.id
)
delete from T
from deleted AS D
inner join tTest20140128 AS T on (
T.id = D.id
)
end
go
-- Sorta "attching listeners to event"
-- tTest20140128_Child01
create trigger tTest20140128_tTest20140128_Child01
on tTest20140128_ID
after delete
as
begin
delete T
from deleted as D
inner join tTest20140128_Child01 AS T on (
T.id = D.id
)
end
go
-- tTest20140128_Child02
create trigger tTest20140128_tTest20140128_Child02
on tTest20140128_ID
after delete
as
begin
delete T
from deleted as D
inner join tTest20140128_Child02 AS T on (
T.id = D.id
)
end
go
-- New tests
insert tTest20140128 values (4), (5), (6)
insert tTest20140128_Child01 values (4), (5), (6)
insert tTest20140128_Child02 values (4), (5), (6)
go
select COUNT (*) as [COUNT after insert] from tTest20140128
go
delete from tTest20140128 -- No Error
go
select COUNT (*) as [COUNT" after delete] from tTest20140128
go
drop table tTest20140128_ID
drop table tTest20140128_Child02
drop table tTest20140128_Child01
drop table tTest20140128
答案 0 :(得分:0)
创建表格听起来不必要......但是你的INSTEAD OF
触发器听起来是个好主意:
如何在tMainTable上创建INSTEAD OF
触发器,首先“删除任何需要在tMainTable行之前删除的内容”,然后“删除tMainTable的实际行”?