【问题标题】:Update Trigger only update if the data has changed更新触发器仅在数据更改时更新
【发布时间】:2016-11-18 04:01:07
【问题描述】:

我有一个更新触发器,当另一个表中的记录被更新时,它会更新空记录。我的问题是数据在网格视图中,当您更新它时,它会在网格中的所有记录上运行更新查询,而不仅仅是更新的记录。因此,当触发器触发时,它会更新目标表中匹配的每一行,但我只想更新数据已更改的那一行。这是我的触发器。

ALTER TRIGGER [dbo].[Trigger_update_DeSchedule] ON [dbo].[tBatchDetails] 
    After UPDATE ,INSERT
AS    

BEGIN
SET NOCOUNT ON
    DECLARE @BatchId int
          , @Ethanol varchar(10)
          , @Glucose varchar(10)
          , @SampleAge varchar(10);

    SELECT @BatchId = B.[BatchID]
        ,@Ethanol = [Ethanol]
        ,@Glucose= [Glucose]
        ,@SampleAge = SA.SampleAge  
    from INSERTED bd
        INNER JOIN  [dbo].[tSampleAge] sa ON SA.SampleAgeID = BD.SampleAge 
        INNER JOIN  [dbo].[tBatch] b ON B.ID =BD.ID

    UPDATE [dbo].[DeSchedule] 
    SET [Ethanol] = @Ethanol
      , [Glucose] = @Glucose
      , [SampleCompleted] = 1 
    WHERE [BatchID] = @BatchId 
        AND [SampleAge] = @SampleAge 
        AND SiteID = 6 
        AND SampleCompleted IS NULL

END

如何在这个触发器中只更新数据发生变化的记录?

【问题讨论】:

标签: sql sql-server


【解决方案1】:

评论太长了。

您应该做的第一件事是将插入和更新触发器分开。在单个触发器中执行它们几乎总是会导致问题。它肯定会在这里给你带来麻烦。您发布的代码应该会在您插入时执行您要查找的操作。

但是,当您更新时,您需要添加要删除的连接。然后您需要为基表中的每一列添加 where 谓词。了解实际值是否已更改的唯一方法是比较插入和删除的值。

类似这样的:

i.ColA <> d.ColA 
OR i.ColB <> d.ColB
etc...

有些人可能会说使用 UPDATE 功能,但这对您不起作用。如果列在要更新的值列表中,则返回 true。它不关心值是否与以前相同。

您当前的触发器正在使用标量值。这不是一个好方法,因为触发器每次操作都会触发一次。您的代码需要基于设置。

【讨论】:

    【解决方案2】:

    触发器是针对每个更新语句而不是更新语句中的每一行触发的,当有更新更新多行时,您在触发器中使用变量将失败/损坏数据。

    ALTER TRIGGER [dbo].[Trigger_update_DeSchedule] ON [dbo].[tBatchDetails] 
        After UPDATE ,INSERT
    AS    
    
    BEGIN
    SET NOCOUNT ON
    
        -- Correct the Alias in the set clause I am not sure what is coming from where
        UPDATE S                    
         SET  S.[Ethanol] = [Ethanol]
            , S.[Glucose] = [Glucose]
            , S.[SampleCompleted] = 1  
        from INSERTED bd
            INNER JOIN  [dbo].[tSampleAge] sa ON SA.SampleAgeID = BD.SampleAge 
            INNER JOIN  [dbo].[tBatch]     b  ON B.ID =BD.ID
            INNER JOIN  [dbo].[DeSchedule] s  ON s.[BatchID] = B.[BatchID] 
                                             AND s.[SampleAge] = BD.SampleAge 
        WHERE SiteID = 6 
          AND SampleCompleted IS NULL
    
    END
    

    【讨论】:

    • 为什么我们要在 DeSCchedule 上加入我们要更新记录的表?
    • @llerdal google SQL Server Syntax for Update with joins 谢谢
    • 由于您正在更新的表的 JOIN 使得更新变得更容易。
    • 即使乙醇和葡萄糖为空,这仍会更新每条记录的样本已完成列。 @M.阿里
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-21
    • 1970-01-01
    • 2011-09-11
    • 1970-01-01
    • 2012-02-02
    • 1970-01-01
    相关资源
    最近更新 更多