检查删除是否由CASCADE DELETE引起

时间:2014-12-30 05:32:57

标签: sql sql-server tsql triggers cascade

我一直在搜索,但无法找到答案。有没有办法让删除触发器检测删除是由DELETE语句还是通过父表上的CASCADE DELETE引起的?

我有表A有PK和表B,表A有FK,有ON DELETE CASCADE。

我想在表B上创建一个删除触发器,用于检查删除是否由表A中的记录删除引起,并允许删除,但如果它是表B上的DELETE语句则阻止删除。 / p>

到目前为止我唯一能解决的是表A上的删除触发器,它禁用表B中的删除触发器,删除表B中的记录,然后再次启用表B上的触发器,但这样做并不是一个优雅的解决方案。

感谢您的任何意见:)

2 个答案:

答案 0 :(得分:0)

假设您知道(或可以确定)所涉及的外键约束,您可以从DBA_CONSTRAINTS查看DELETE_RULE列

SELECT constraint_name, delete_rule
FROM dba_constraints
WHERE r_constraint_name = <<name of the primary key constraint>>
AND r_owner = <<owner of the primary key constraint>>
AND delete_rule = 'CASCADE'

答案 1 :(得分:0)

我最终使用Trigger选项,因为它看起来是最优雅的解决方案,并且在我实际编写脚本之后看起来并不太糟糕。这是脚本,如果它可以帮助其他人或任何人想要评论它:

/* 
Create the MAILBOXES CRPREDEL1 Trigger 
Creates the Trigger which Deletes all Folders ( and by Cascade all Files ) when a Mailbox gets Deleted
*/
CREATE TRIGGER [dbo].[CRPREDEL1_MBX]
ON [dbo].[MAILBOXES]
INSTEAD OF DELETE
NOT FOR REPLICATION
AS
    DECLARE @SqlIdentity        int

    IF @@ROWCOUNT > 0
    BEGIN
        SET NOCOUNT ON
        DECLARE c_primary CURSOR LOCAL FOR SELECT d.MBX_SQLIDENTITY
                                           FROM deleted d
        BEGIN
            OPEN c_primary
            FETCH NEXT FROM c_primary INTO @SqlIdentity
            WHILE @@FETCH_STATUS = 0
            BEGIN
                -- Disable CRPOSDEL1_MFO so we can delete System Folders
                ALTER TABLE [MAILBOX_FOLDERS] DISABLE TRIGGER [CRPOSDEL1_MFO]

                -- Delete the Mailbox Folders
                DELETE FROM [MAILBOX_FOLDERS] WHERE [MFO_MAILBOX] = @SqlIdentity

                -- Enable CRPOSDEL1_MFO so System Folders can't be deleted anymore
                ALTER TABLE [MAILBOX_FOLDERS] ENABLE TRIGGER [CRPOSDEL1_MFO]

                -- Delete the Actual Mailbox now
                DELETE FROM [MAILBOXES] WHERE [MBX_SQLIDENTITY] = @SqlIdentity  

                FETCH NEXT FROM c_primary INTO @SqlIdentity
            END
            CLOSE c_primary
        END
        DEALLOCATE c_primary
    END
GO

感谢投票人员,感谢它!