disadvantage of having multiple triggers on the sa

2019-09-12 09:34发布

问题:

I have multiple triggers on the same table the reason for using multiple triggers is because there are fields need to be updated from different tables also i have backward date scheduling. something wired is going on When i first insert, only one field from one of the triggers updated or one of the trigger fired, when i update row for the first time three trigger fired,... I have to update 3 time to get all fields updated also takes around 8 second every time when i do the first, second, third time updates

question 1. what are the disadvantage of having multiple triggers in the single table?

question 2. How can i speed up triggers?

question 3. how can i debug triggers?

back order Scheduling

SHIP BY = CUSTOMER PROMISED DATE-1

A-MOUNT BY = SHIP BY -1

A-POWDER BY = A-MOUNT BY - 1 OR A-POWDER BY also equal ship by date -2

A-FAB BY= A-POWDER BY - 1 OR A-FAB BY also equal ship by date -3

A-C/S BY = A-FAB BY OR A-C/S BY also equal ship by date -4

A-CUT BY = A-C/S BY -1 OR A-CUT BY also equal ship by date -5

/****** Object:  Trigger [dbo].[CALC-PROMISED-DATE-AND-SHIPBY]    Script Date: 4/6/2017 2:46:01 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[CALC-PROMISED-DATE-AND-SHIPBY] 
    ON [dbo].[WORKORDERS]
    AFTER  INSERT, UPDATE
    AS 
    BEGIN
    set nocount on
     IF TRIGGER_NESTLEVEL() > 1
     RETURN
     set datefirst 7;
UPDATE T1
    [SHIP BY] = 
              CASE datepart(WEEKDAY, t1.[CALC PROMISED DATE])
                    WHEN 1 then DateAdd( day, -2, t1.[CALC PROMISED DATE])
                    WHEN 7 then DateAdd( day, -1, t1.[CALC PROMISED DATE])
                ELSE
                    CASE 
                        WHEN t1.[RE-COMMIT DATE] =Null THEN ISNULL(T1.[PROMISED DATE],Null)
                         WHEN t1.[RE-COMMIT DATE] is null THEN ISNULL(T1.[PROMISED DATE],Null)
                    ELSE ISNULL(T1.[RE-COMMIT DATE],Null)
                    END
            END       

            FROM WORKORDERS T1
                 INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #]
                END

A-MOUNT BY

    /****** Object:  Trigger [dbo].[MOUNTBY]    Script Date: 4/6/2017 2:46:54 PM ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    ALTER TRIGGER [dbo].[MOUNTBY] 
        ON [dbo].[WORKORDERS]
        AFTER  INSERT,UPDATE
        AS 
        BEGIN
         IF TRIGGER_NESTLEVEL() > 1
         RETURN
         set datefirst 7;
    UPDATE T1 
        [A-MOUNT BY] = 
        case       datepart(WEEKDAY,  DateAdd(day,-1,t1.[SHIP BY]))
             when 7 then DateAdd( day, -2, t1.[SHIP BY] )
             when 1 then DateAdd( day, -3, t1.[SHIP BY] )
            else   DateAdd( day, -1, t1.[SHIP BY] )--t1.[A-C/S BY]-1
        END
FROM WORKORDERS T1
     INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #]
    END

A-POWDER BY

   /****** Object:  Trigger [dbo].[POWDERBY]    Script Date: 4/6/2017 2:49:53 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[POWDERBY] 
    ON [dbo].[WORKORDERS]
    AFTER INSERT,UPDATE
    AS 
    BEGIN
     IF TRIGGER_NESTLEVEL() > 1
     RETURN
     set datefirst 7;
UPDATE T1 
--SET
SET [A-POWDER BY] = 
case datepart(WEEKDAY, t1.[A-MOUNT BY]-1 )
      when 7 then DateAdd( day, -2, t1.[A-MOUNT BY] )
     when 1 then DateAdd( day, -3, t1.[A-MOUNT BY])
    else  t1.[A-MOUNT BY]-1 
END

FROM WORKORDERS T1
     INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #]
    END

A-FAB BY

   /****** Object:  Trigger [dbo].[FABBY]    Script Date: 4/6/2017 2:50:23 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[FABBY] 
    ON [dbo].[WORKORDERS]
    AFTER insert, UPDATE
    AS 
    BEGIN
     IF TRIGGER_NESTLEVEL() > 1
     RETURN
     set datefirst 7;
UPDATE T1 
SET [A-FAB BY] =  case datepart(WEEKDAY, t1.[A-POWDER BY]-1 )
      when 7 then DateAdd( day, -2, t1.[A-POWDER BY] )
     when 1 then DateAdd( day, -3, t1.[A-POWDER BY])
    else  t1.[A-POWDER BY]-1 
END
FROM WORKORDERS T1
     INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #]
    END

a-PRINT BY

   /****** Object:  Trigger [dbo].[PRINTBY]    Script Date: 4/6/2017 2:50:50 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[PRINTBY] 
    ON [dbo].[WORKORDERS]
    AFTER INSERT, UPDATE
    AS 
    BEGIN
     IF TRIGGER_NESTLEVEL() > 1
     RETURN
     set datefirst 7;
UPDATE T1
SET [A-PRINT BY] = case datepart(WEEKDAY, t1.[A-FAB BY] )
      when 7 then DateAdd( day, -2, t1.[A-FAB BY])
     when 1 then DateAdd( day, -3, t1.[A-FAB BY])
    else  t1.[A-FAB BY]-1 
END
FROM WORKORDERS T1
     INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #]
    END

A-C/S BY

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[C/SBY] 
    ON [dbo].[WORKORDERS]
    AFTER  INSERT,UPDATE
    AS 
    BEGIN
     IF TRIGGER_NESTLEVEL() > 1
     RETURN
     set datefirst 7;
UPDATE T1 
--SET
SET [A-C/S BY] =  case datepart(WEEKDAY, t1.[A-PRINT BY]-1 )
      when 7 then DateAdd( day, -2, t1.[A-PRINT BY] )
     when 1 then DateAdd( day, -3, t1.[A-PRINT BY])
    else  t1.[A-PRINT BY]-1 
END
FROM WORKORDERS T1
     INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #]
    END

A-CUT BY

  SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[CUTBY] 
    ON [dbo].[WORKORDERS]
    AFTER INSERT, UPDATE
    AS 
    BEGIN
     IF TRIGGER_NESTLEVEL() > 1
     RETURN
     set datefirst 7;
UPDATE T1 
--SET
SET [A-CUT BY] = 
case       datepart(WEEKDAY,  DateAdd(day,-1,t1.[A-C/S BY]))
     when 7 then DateAdd( day, -2, t1.[A-C/S BY] )
     when 1 then DateAdd( day, -3, t1.[A-C/S BY] )
    else   t1.[A-C/S BY]-1--t1.[A-C/S BY]-1
END
FROM WORKORDERS T1
     INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #]
    END

回答1:

This is really 3 questions rolled into one post.

question 1. what are the disadvantage of having multiple triggers in the single table?

There is no disadvantage here as long as each trigger is for a unique event. It is generally best to avoid having three update triggers on a single table because it is difficult to maintain and sometimes the fire order is important so you would have to manage that as well.

question 2. How can i speed up triggers?

There is no catch-all magic button to make triggers go faster. The queries and logic for each trigger needs to be evaluated independently.

question 3. how can i debug triggers?

With print statements. Triggers are definitely not easy to debug.


This question however lends itself to a larger discussion of triggers. Most of the time triggers are not the best approach to a problem. There are often times better approaches. I have been working with databases for over 2 decades at this point and have had a legitimate need for a trigger only a handful of times. They can be extremely useful for auditing but most of the time they are the wrong tool for the task at hand.


Given the new information and code I have created a new trigger that should work for you. You don't need a trigger for each column, you need a trigger for the event of insert and update. You can do all these edits in a single update statement. There still seems to be some major logic issues here but I don't really know what you are trying to do. I would suggest dropping all of those triggers as they very poorly named and given the name they are sort of stuck into a single action.

I would also highly recommend that you get in the habit of better names. These column names are just dreadful. They shouldn't have spaces, dashes etc.

ALL of those triggers can be simplified to something like this.

create TRIGGER [dbo].[WORKORDERS_Insert_Update] ON [dbo].[WORKORDERS]
    AFTER  INSERT, UPDATE AS 
BEGIN
    set nocount on

    IF TRIGGER_NESTLEVEL() > 1
        RETURN

    set datefirst 7;
    UPDATE T1
        set [SHIP BY] = 
            CASE datepart(WEEKDAY, t1.[CALC PROMISED DATE])
                WHEN 1 then DateAdd( day, -2, t1.[CALC PROMISED DATE])
                WHEN 7 then DateAdd( day, -1, t1.[CALC PROMISED DATE])
            ELSE T1.[RE-COMMIT DATE]
                    --CASE This entire case expression is pointless. Just put in the column, all the NULL checks in here are going to do the exact same thing.
                    --    --WHEN t1.[RE-COMMIT DATE] = Null THEN ISNULL(T1.[PROMISED DATE],Null) Nothing EVER equals NULL. This will never happen
                    --     --WHEN t1.[RE-COMMIT DATE] is null THEN ISNULL(T1.[PROMISED DATE],Null) ??? Why check for NULL and if it is NULL use an explicit NULL. This makes no sense
                    --ELSE ISNULL(T1.[RE-COMMIT DATE],Null)??? Why check for NULL and if it is NULL use an explicit NULL. This makes no sense
                    --END
            END       
        , [A-MOUNT BY] = 
            case datepart(WEEKDAY,  DateAdd(day,-1,t1.[SHIP BY]))
                when 7 then DateAdd( day, -2, t1.[SHIP BY] )
                when 1 then DateAdd( day, -3, t1.[SHIP BY] )
                else DateAdd( day, -1, t1.[SHIP BY] )--t1.[A-C/S BY]-1
            END
        , [A-POWDER BY] = 
            case datepart(WEEKDAY, t1.[A-MOUNT BY]-1 )
                when 7 then DateAdd( day, -2, t1.[A-MOUNT BY] )
                when 1 then DateAdd( day, -3, t1.[A-MOUNT BY])
                else t1.[A-MOUNT BY]-1 
            END
        , [A-FAB BY] = 
            case datepart(WEEKDAY, t1.[A-POWDER BY]-1 )
                when 7 then DateAdd( day, -2, t1.[A-POWDER BY] )
                when 1 then DateAdd( day, -3, t1.[A-POWDER BY])
                else  t1.[A-POWDER BY]-1 
            END
        ,[A-PRINT BY] = 
            case datepart(WEEKDAY, t1.[A-FAB BY] )
                when 7 then DateAdd( day, -2, t1.[A-FAB BY])
                when 1 then DateAdd( day, -3, t1.[A-FAB BY])
                else  t1.[A-FAB BY]-1 
            END
        , [A-C/S BY] = 
            case datepart(WEEKDAY, t1.[A-PRINT BY]-1 )
                when 7 then DateAdd( day, -2, t1.[A-PRINT BY] )
                when 1 then DateAdd( day, -3, t1.[A-PRINT BY])
                else  t1.[A-PRINT BY]-1 
            END
        , [A-CUT BY] = 
            case datepart(WEEKDAY,  DateAdd(day,-1,t1.[A-C/S BY]))
                when 7 then DateAdd( day, -2, t1.[A-C/S BY] )
                when 1 then DateAdd( day, -3, t1.[A-C/S BY] )
                else   t1.[A-C/S BY]-1--t1.[A-C/S BY]-1
            END
    FROM WORKORDERS T1
    INNER JOIN inserted i ON T1.[WORK ORDER #] = i.[WORK ORDER #]
END