SQL:删除所有嵌套的自引用记录
这是表的结构:Id Name ParentId ParentId是主列Id的外键。现在让我们假设我有几行,如:仅显示来自行的ParentIdSQL:删除所有嵌套的自引用记录,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,这是表的结构:Id Name ParentId ParentId是主列Id的外键。现在让我们假设我有几行,如:仅显示来自行的ParentId 01 / \ 5 2 / \ 3 4 我已设置为取代Delete触发器,如下所示: CREATE TRIGGER [dbo].[tr_tb] ON [dbo].[Some_tb] INSTEAD OF DELETE AS /*Delete from another
01
/ \
5 2
/ \
3 4
我已设置为取代Delete触发器,如下所示:
CREATE TRIGGER [dbo].[tr_tb] ON [dbo].[Some_tb]
INSTEAD OF DELETE
AS
/*Delete from another table*/
DELETE FROM SomeOther_tb WHERE OtherId IN(SELECT Id FROM deleted);
/*Delete childs from this table*/
DELETE FROM Some_tb WHERE ParentId IN(SELECT Id FROM deleted);
/*Delete from this table*/
DELETE FROM Some_tb WHERE Id IN(SELECT Id FROM deleted);
当Id=01的记录被删除时,检查上面孩子的表示。仅删除Id为5,2的直接子记录,留下Id为3,4的子记录
我假设childs Id=5,2时不会触发InsteadOfTrigger函数
如何解决此问题,以便删除所有嵌套的子对象 MS SQL Server 2008支持通用表表达式CTE,这对于分层数据非常有用。触发器中也可能存在CTE
CREATE TRIGGER [dbo].[tr_tb] ON [dbo].[Some_tb]
INSTEAD OF DELETE
AS
DECLARE @DELETED TABLE(
ID BIGINT
)
INSERT INTO @DELETED
SELECT Id FROM deleted
--could use a CTE here as well for better performance
WHILE @@ROWCOUNT>0
BEGIN
INSERT INTO @DELETED
SELECT Id
FROM Some_tb t
inner join @DELETED d on d.parentid=t.id
END
/*Delete from another table*/
DELETE FROM SomeOther_tb WHERE OtherId IN(SELECT Id FROM @DELETED);
/*Delete childs from this table*/
DELETE FROM Some_tb WHERE ParentId IN(
SELECT Id FROM @DELETED WHERE ID NOT IN (SELECT ID FROM DELETED)
);
/*Delete from this table*/
DELETE FROM Some_tb WHERE Id IN(SELECT Id FROM DELETED);
CREATE TRIGGER [dbo].[tr_tb] ON [dbo].[Some_tb]
INSTEAD OF DELETE
AS
/*Delete from another table*/
;with tbl as (--this is CTE
--anchor query (top level)
select t.id, t.parentid
from someOther_tb t
inner join deleted d on d.id = t.parentid
union all
--recursive query
select t.id, t.parentid
from someOther_tb t
inner join tbl on tbl.id=t.parentid
)
delete someOther_tb
where id in (select id from tbl)
--Now it is safe to delete from main table
DELETE FROM Some_tb WHERE Id IN(SELECT Id FROM deleted)
为什么不利用级联删除,因为这似乎正是您正在做的事情?不能,因为有多个级联路径:所以这是一个自连接表?是的,在某种程度上。ParentId引用同一个表中的Id非常感谢您的回答。我尝试了一些CTE的东西,并写了自己的答案。非常感谢您的意见/建议。谢谢Alex,我想从其他人那里知道tb不在这里,因为ParentId和Id来自同一张表。顺便说一句,我添加了一个关于CTE实施的答案。一定要让我知道您对此的看法。您是说OP中的某些\u tb和其他\u tb是同一个表吗?这里的目标是删除某些\u tb的所有嵌套子级,包括与某些\u tb引用的其他\u tb的记录。问题中所描述的问题是,所有嵌套的子项都没有被删除。正如您在我的回答中看到的,它们现在被删除了。如果其他人有自己的层次结构,那么在锚查询中选择顶级id就足够了。对不起,我无法理解您的答案。不管怎样,我已经投了更高的票。没有必要在@deleted中table@AlexKudryashev那么如何插入CTE找到的新ID?已删除的联合?不需要插入它们。直接使用CTE删除所需内容。
CREATE TRIGGER [dbo].[tr_tb] ON [dbo].[Some_tb]
INSTEAD OF DELETE
AS
/*Delete from another table*/
;with tbl as (--this is CTE
--anchor query (top level)
select t.id, t.parentid
from someOther_tb t
inner join deleted d on d.id = t.parentid
union all
--recursive query
select t.id, t.parentid
from someOther_tb t
inner join tbl on tbl.id=t.parentid
)
delete someOther_tb
where id in (select id from tbl)
--Now it is safe to delete from main table
DELETE FROM Some_tb WHERE Id IN(SELECT Id FROM deleted)