从 SQL 中的多个表中级联删除行
Posted
技术标签:
【中文标题】从 SQL 中的多个表中级联删除行【英文标题】:Cascade delete rows from multiple tables in SQL 【发布时间】:2021-11-06 13:58:42 【问题描述】:我有 3 个这样的表:
表 1:ID、名称 表 2:ID、名称 表 3:Id、EntityName (nvarchar)、EntityId (int)Table3 上没有外键。我将 Table1 和 Table2 的行插入到 Table3 中,如下所示:
Id | EntityName | EntityId | OtherColumn(s) |
---|---|---|---|
1 | Table1 | 1 | ... |
2 | Table2 | 1 | ... |
3 | Table2 | 2 | ... |
当我从 Table1 或 Table2 中删除一行时,如何将它从 Table3 中级联?
【问题讨论】:
这能回答你的问题吗? SQL Server ON DELETE Trigger 只需使用触发器而不是任何地方的任何级联。 【参考方案1】:您可以在每个表上创建一个delete trigger
,以从table3中删除匹配的行,例如:
create trigger Table1Delete on dbo.table1
for delete
as
if @@RowCount = 0 return
set nocount on
delete from t3
from deleted d
join table3 t3 on t3.EntityName='Table1' and d.Id=t3.EntityId
Table2
也有类似的
【讨论】:
我太专注于级联删除,我完全忘记了触发器。 旁白:我会使用not exists ( select 42 from deleted )
,而不是@@RowCount = 0
。它避免了由于在检查之前插入语句或由于merge
语句而触发触发器而可能导致的任何混淆。
Using @@rowcount
来自文档和微软推荐的内容;尽管在以后的版本中不再是这种情况,但在旧版本中访问插入/删除的表是一项代价高昂的操作,需要尽量减少。【参考方案2】:
这就是您可以编写查询以“模仿”级联删除的方式:
delete from table2 t2
where exists(select 1 from table3
where t2.id = entityId and EntityName = 'Table2')
delete from table1 t1
where exists(select 1 from table3
where t1.id = entityId and EntityName = 'Table1')
如果您有从 table3
中删除的某些条件,您还应该在这些查询中包含它。
更新
要自动执行此操作,您需要使用级联删除操作定义外键。但是只能在列上定义一个外键,因此您需要有两列——一列用于引用table1
,第二列用于引用table2
。然后你需要定义级联删除。
使用当前设计(一列引用多个表)这是不可能的,您需要解决(建议在表上实现删除触发器)。
【讨论】:
我写这些查询没有问题。我问有没有办法用外键做到这一点。 @YSFKBDY 查看更新。 我有两个引用:EntityName 和 EntityId。以上是关于从 SQL 中的多个表中级联删除行的主要内容,如果未能解决你的问题,请参考以下文章