我希望触发器从sql server中的2个表中删除

时间:2015-03-16 15:10:50

标签: sql-server triggers delete-row

我有2个SQL Server表(A和B)。

我想从以下位置删除行: A,使用一个触发器删除B中的行时。

我想从以下位置删除行: B,使用一个触发器删除A中的行时。

到目前为止,这是我的触发器:

 CREATE TRIGGER instead_delete
 ON A INSTEAD of DELETE as

 DELETE B 
 FROM B, deleted
 WHERE B.Id = deleted.Id

 DELETE A 
 FROM A, deleted
 WHERE A.Id = deleted.Id 

我的第二个触发器:

 CREATE TRIGGER after_delete
 ON B AFTER DELETE as

 DELETE A 
 FROM A, deleted
 WHERE A.Id = deleted.Id

但它无法正常工作。 我得到一个直接的递归。 (而不是触发器不支持直接递归。触发器执行失败 - 这个错误)。

我该如何解决?

1 个答案:

答案 0 :(得分:0)

我想删除具有外键约束的自引用表中的记录层次结构。使用AFTER DELETE触发器不起作用,因为在它到达之前违反了外键约束。使用INSTEAD OF触发器不起作用,因为它抛出“INSTEAD OF触发器不支持直接递归”错误。更改数据库的直接和间接设置无效。我找不到任何解决方案。我能想到的唯一解决方案是使用CTE选择层次结构中具有深度/级别编号的所有记录,并使用光标从最大深度逐个删除记录以避免外键冲突。以下是示例触发器:

CREATE TRIGGER [dbo].[relatedAccountInsteadOfDelete] 
   ON  [dbo].[relatedAccount] 
   INSTEAD OF DELETE
AS 
BEGIN
    SET NOCOUNT ON;

    -- log deleted related accounts 
    with relatedAccounts as ( 
        select
            ra1.[guid]
            ,ra1.relatedAccount_guid
        from
            relatedAccount ra1
        inner join 
            deleted d
        on
            d.[guid] = ra1.[guid]
        union all
        select
            ra1.[guid]
            ,ra1.relatedAccount_guid
        from
            relatedAccount ra1
        inner join 
            relatedAccounts ra2
        on
            ra2.[guid] = ra1.relatedAccount_guid
        where
            ra1.relatedAccount_guid is not null
    )
    insert into relatedAccount_history select ra1.* from relatedAccount ra1 inner join relatedAccounts ra2 on ra2.[guid] = ra1.[guid];

    -- delete related entities 
    with relatedAccounts as ( 
        select
            ra1.[guid]
            ,ra1.relatedAccount_guid
        from
            relatedAccount ra1
        inner join 
            deleted d
        on
            d.[guid] = ra1.[guid]
        union all
        select
            ra1.[guid]
            ,ra1.relatedAccount_guid
        from
            relatedAccount ra1
        inner join 
            relatedAccounts ra2
        on
            ra2.[guid] = ra1.relatedAccount_guid
        where
            ra1.relatedAccount_guid is not null
    )
    delete from dbo.relatedEntity where [guid] in (select t1.[guid] from relatedAccounts d inner join dbo.relatedEntity t1 on t1.relatedAccount_guid=d.[guid]);

    -- delete related accounts
    declare @guid uniqueidentifier;

    -- select all accounts to any depth in their hierarchy
    declare relatedAccounts_cursor cursor for
    with relatedAccounts as ( 
        select
             1 as depth
            ,ra1.[guid]
            ,ra1.relatedAccount_guid
        from
            relatedAccount ra1
        inner join 
            deleted d
        on
            d.[guid] = ra1.[guid]
        union all
        select
            ra2.depth + 1 as depth
            ,ra1.[guid]
            ,ra1.relatedAccount_guid
        from
            relatedAccount ra1
        inner join 
            relatedAccounts ra2
        on
            ra2.[guid] = ra1.relatedAccount_guid
        where
            ra1.relatedAccount_guid is not null
    )
    select [guid] from relatedAccounts order by depth desc;

    -- delete accounts from the bottom up to avoid violating foriegn key constraints
    open relatedAccounts_cursor

    fetch next from relatedAccounts_cursor
    into @guid

    while @@fetch_status = 0
    begin

        delete from dbo.relatedAccount where [guid] = @guid; 

        fetch next from relatedAccounts_cursor
        into @guid

    end

    close relatedAccounts_cursor;
    deallocate relatedAccounts_cursor;

END