防止触发器发射

时间:2012-07-31 07:44:13

标签: sql sql-server

我有以下触发器

第一次触发:

ALTER TRIGGER [dbo].[DIENSTLEISTUNG_Update]
ON [dbo].[DIENSTLEISTUNG]
INSTEAD OF UPDATE
AS

BEGIN
    SET  NOCOUNT ON;
    DECLARE @intNewID int

         INSERT INTO [DIENSTLEISTUNG] 
         (DESCRIPTION, QUANTITY, 
         PRICE, AZ_MO, AZ_DI,AZ_MI,AZ_DO,AZ_FR,
         AZ_SA,AZ_SO,DIENSTLEISTUNGSART_ID,
         UPDATE_USER, UPDATE_DATE,
         PERMISSIONS, KONTRAKTPOSITION,ITEMNUMBER,
         PRIORITY, VALID)

         SELECT  i.DESCRIPTION, i.QUANTITY, i.PRICE, i.AZ_MO, 
         i.AZ_DI,i.AZ_MI,i.AZ_DO,i.AZ_FR,       
         i.AZ_SA,i.AZ_SO,i.SERVICETYPE_ID, i.UPDATE_USER,GETDATE(),
         i.PERMISSIONS, i.KONTRAKTPOSITION,i.ITEMNUMBER, i.PRIORITY, 'Y'

         FROM INSERTED i
         JOIN deleted d ON i.ID=d.ID
         WHERE i.PRICE<>d.PRICE
         or i.DESCRIPTION<>d.DESCRIPTION


         IF ( UPDATE (PRICE) OR UPDATE (DESCRIPTION) )
         UPDATE  S
         SET  s.VALID = 'N'    
         FROM SERVICE s
         JOIN INSERTED i ON I.ID = S.ID


         IF UPDATE(PRIORITY)
         UPDATE s
         SET s.PRIORITY= i.PRIORITY
         FROM SERVICE s
         JOIN INSERTED i ON i.ID = s.ID

   SET NOCOUNT OFF;      
END

如果原始行发生更改,第一个Trigger会使用新ID复制整行,触发器也会设置一个标志。旧行获取标志VALID = 'N',新行获取标志VALID = 'Y'。如果PRICEDESCRIPTION更新,则触发器仅会创建新行。到现在为止还挺好。

我的问题是,如果我想更新新行中的PRIORITY,则触发器再次触发并将标志设置为VALID = 'N'。这不应该发生。我只想更新优先级而不创建新行或更新另一列。

感谢您的帮助

3 个答案:

答案 0 :(得分:2)

无法阻止触发器触发 - 如果它存在且未禁用,将触发。这就是触发器的工作方式。

可以做的是检查触发器内哪些列已更新。所以你可以在一个单一的触发器中做这样的事情:

CREATE TRIGGER [dbo].[DIENSTLEISTUNG_Update]
ON [dbo].[DIENSTLEISTUNG]
FOR UPDATE
AS
    IF UPDATE(PRICE) 
      ... (do what you need to do if PRICE is updated)...

    IF UPDATE(DESCRIPTION)
      ... (do what you need to do if DESCRIPTION is updated)...

    IF UPDATE(PRIORITY)
      ... (do what you need to do if PRIORITY is updated)...

使用UPDATE()函数检查给定列是否已更新 - 如果已更新,请对其执行操作。请参阅MSDN docs on how to use the UPDATE() function

答案 1 :(得分:1)

您可以仅在某些列或一列上触发触发器。 像这样。

CREATE TRIGGER tr_something ON myTable
FOR INSERT, UPDATE
AS
IF UPDATE(myColumn)
BEGIN
--       do what you want
END

下面的帖子提供了更多细节,似乎我要慢一点:)

答案 2 :(得分:0)

您可以做的是设置您所在会话的上下文信息:

SET Context_Info 0x55555

然后在您的触发器中检查上下文信息以决定要做什么:

DECLARE @Cinfo VARBINARY(128)  
SELECT @Cinfo = Context_Info()  
IF @Cinfo = 0x55555  
    RETURN