SQL:删除所有嵌套的自引用记录

时间:2016-07-15 16:07:30

标签: sql sql-server sql-server-2008

这是表格的结构:Id Name ParentId

ParentId是主要列Id的外键。现在假设我有几行如下:(仅显示行中的ParentId

     01
   /    \
  5      2
        / \
       3   4

我已设置InsteadOfDelete触发器,如下所示:

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)。

我假设没有为孩子(InsteadOfTrigger)触发Id=5,2个功能。

如何解决此问题,以便删除所有嵌套的子项?

3 个答案:

答案 0 :(得分:2)

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);

答案 1 :(得分:1)

MS SQL Server 2008支持通用表表达式(CTE),它们非常适合分层数据。并且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)

答案 2 :(得分:0)

$user->newSubscription('premium','monthly')->trialDays(5)->create($stripeToken,['email' => $user->email], "")