【发布时间】:2020-12-31 02:30:24
【问题描述】:
我有这个用户表,其中有很多列,我想要做的是仅在其中一个列值更改而不是整行时触发触发器。
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 列是否发生更改,然后才需要更新表。否则我希望这个触发器什么都不做。
【问题讨论】:
-
您的触发器有一个严重的问题:它假定所有更新都只会影响一行。
-
有了触发器,写一个更新语句,会影响两个不同的用户(例如
UPDATE dbo.Users SET AdCount += 1 WHERE ID IN (1,2);),看看触发器是否更新了他们两个的数据。 (答案是否定的。) -
如果两个用户尝试同时更新同一行,一个会赢,另一个会丢失更新。这不是我在这里要讨论的问题。刷新链接并阅读“不准备多行更新”部分 - 我更新了示例以与您的场景更相关(当然没有任何广告计数逻辑)。
-
再来一次,这不是关于两个不同的人同时更新一行,而是关于编写安全代码并超出了这个单一项目的范围,但我放弃了。祝你好运。
标签: sql sql-server tsql triggers