首页 > 解决方案 > 使用触发器在该行中只有一个列值更改时更新当前行中的数据

问题描述

我有这个用户表,其中有很多列,我想做的是仅在其中一个列值更改而不是整行时触发触发器。

USE [TempInvestManage]
GO
/****** Object:  Trigger [dbo].[DailyEarning2]    Script Date: 9/13/2020 4:32:21 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[DailyEarning2] ON [dbo].[Users]
after update
as        
    DECLARE @UId INT
    declare @AdCount INT

    SELECT @UId = inserted.ID, @AdCount = inserted.AdCount     
    FROM INSERTED;

    with firstCte(Name,UID,PName,AdCount,ClickRate,ReferComission)
    as
    (
        select distinct Users.Name, Users.ID, Packages.PName, Users.AdCount, Packages.ClickRate, Packages.ReferCommission
        from Users
        inner join UserPackages on UserPackages.U_ID = Users.ID
        inner join Packages on Packages.PID = UserPackages.P_ID
        where U_ID = @UId and UserPackages.PackageStatus = 'true' 
    )
    update Users set DailyEarning = ClickRate * @AdCount
    from firstCte
    where ID = @UId and @AdCount != 0;

    update Users set TotalDailyEarning = TotalDailyEarning+DailyEarning, DailyEarning=0
    where ID = @UId and AdCount = 0;

表图片

您现在可以忽略连接。我只需要以某种方式检查adCount触发此触发器时列是否更改,然后才需要更新表。否则我希望这个触发器什么都不做。

标签: sqlsql-servertsqltriggers

解决方案


我相信,这是一个触发器,它实现了您想要的逻辑正常工作。注意事项:

  1. 无需 CTE,直接更新源表即可。
  2. CASE使用表达式将所有更新组合成一个更新。
  3. 以基于集合的方式使用Inserted,以确保您处理多行更新。在这种情况下WHERE U.ID IN (SELECT ID FROM Inserted),工作。
  4. 为您的表命名以使您的查询更加简洁易读。
ALTER TRIGGER [dbo].[DailyEarning2] ON [dbo].[Users]
AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    IF UPDATE(AdCount)
    BEGIN
        UPDATE U set
            DailyEarning = CASE WHEN AdCount != 0 THEN ClickRate * AdCount ELSE 0 END
            , TotalDailyEarning = TotalDailyEarning + CASE WHEN AdCount = 0 THEN DailyEarning ELSE 0 END
        FROM Users U
        INNER JOIN UserPackages UP on UP.U_ID = U.ID
        INNER JOIN Packages P on P.PID = UP.P_ID
        WHERE U.ID IN (SELECT ID FROM Inserted)
        AND UserPackages.PackageStatus = 'true';
    END;
END;

注意:您需要仔细检查我的逻辑是否符合您的要求。


推荐阅读