简体   繁体   中英

How to disable trigger when a Cascade On Delete if fired

Let me start out trying to explain… My MSSQL2008 R2 database has two tables, one called SalesHeader the other SalesDetails . If I delete a header record it cascades and deletes all details related to that header. I also have an on delete trigger on the SalesDetails table that renumbers the DetailNumber field for the remaining details.

The Cascade on delete worked before I put in the Trigger on the Details table. The trigger works now but I get an error when trying to delete a header record. I can manually disable the delete trigger on details table and the header delete works as expected.

To fix this I am not quite sure whether a new on delete trigger on the header table that would disable the trigger on the details table would work or if there is a way to detect the Cascade on Delete in the Details trigger so the trigger logic could be bypassed. I have read here on SO that INSTEAD OF DELETE Triggers are not allowed with Cascade on Delete.

Any suggestions would be greatly appreciated and code snippets even more so.

Cheers,

SQL Trigger:

    USE [MyDatabase]
    GO

    /****** Object:  Trigger [dbo].[OnDeleteTrigger]    Script Date: 9/11/2014 11:51:40 AM ******/
    SET ANSI_NULLS ON
    GO

    SET QUOTED_IDENTIFIER ON
    GO


    -- =============================================
    -- Author:      Randy Gordey
    -- Create date: 08/28/2014
    -- Description: Renumbers the remaining details
    --              when rows are deleted.
    -- =============================================
    CREATE TRIGGER [dbo].[OnDeleteTrigger] 
       ON  [dbo].[SalesDetail] 
       AFTER DELETE
    AS 
    BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for trigger here
    PRINT 'Delete Trigger Fired'
    DECLARE @ID int
    DECLARE @RowNum int
    DECLARE @TransactionNumber int

    -- Gets the TransactionNumber from the deleted row
    SET @TransactionNumber = (SELECT
       intTransactionNumber
    FROM DELETED)

    DECLARE myCursor CURSOR

    /** Gets a collection of the detail lines for this Transaction **/
    LOCAL SCROLL STATIC FOR SELECT
       intDetailNumber,
       ROW_NUMBER() OVER (ORDER BY intDetailNumber) AS 'RowNum'
    FROM SalesDetail
    WHERE intTransactionNumber = @TransactionNumber;

    OPEN myCursor;

    -- Grabs the first row
    FETCH NEXT FROM myCursor INTO @ID, @RowNum;

    -- Begin Loop
    WHILE @@FETCH_STATUS = 0 BEGIN

    /** Updates Database: Setting new Detail Number for each row. **/
    UPDATE SalesDetail
    -- intDetailNumber is part of the PrimaryKey but it is not
    -- set as an identity, so we can still change it.
       SET intDetailNumber = @RowNum
       WHERE intDetailNumber = @ID
       AND intTransactionNumber = @TransactionNumber;

    -- Grabs the next row
    FETCH NEXT FROM myCursor INTO @ID, @RowNum;

    END;
    CLOSE myCursor;
    DEALLOCATE myCursor;

    END
    GO

I found my fix.

    SET @Count = (SELECT
    COUNT(*)
    FROM DELETED)

    -- We want to break for multiple rows (ON DELETE CASCADE)
    IF (@Count > 1) RETURN

I only delete single rows from the ChildTable at a time. I also want to keep the cascade on delete - as my ChildTable has Children of its own.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM