T-SQL仅在列值更改时触发

时间:2016-02-20 16:09:46

标签: sql sql-server triggers

我正在使用SQL Server 2008并具有以下触发器:

USE [gatordata]
GO
/****** Object:  Trigger [dbo].[TriggerUserAssigned] Script Date:2/20/2016 3:42:05 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[TriggerUserAssigned]
ON [dbo].[User]
AFTER UPDATE
AS
IF UPDATE([AssignedToUser]) 
BEGIN
declare @Id int;
declare @AssignedToUser nvarchar(50);
declare @TimeStamp datetime;
declare @Hour bit;
declare @RushService bit;
declare @Status nvarchar(50);
select @Id=i.Id from inserted i;
select @AssignedToUser=i.AssignedToUser from inserted i;
select @Hour=i.[Hour] from inserted i;
select @RushService=i.[RushService] from inserted i;
select @Status=i.[Status] from inserted i;

INSERT INTO [Messages]  
(RequestID,AssignedToUser,[TimeStamp],[Hour],RushService,[Status],MessageText) VALUES (@Id,@AssignedToUser,GETDATE(),@Hour,@RushService,@Status,'New Critical Request')
END

这工作正常,但我需要修改它,因此当“AssignedToUser”列实际更改为新值时,它只会触发插入“Messages”表。如果更新行时“AssignedToUser”的值保持不变,则不应触发触发器。提前谢谢SO朋友......

2 个答案:

答案 0 :(得分:4)

假设您在Users上拥有主键,这并不困难。我假设主键是RequestId

然后:

insert into messages( . . . )
    select i.id, i.assignedtouser, i.hour, i.rushservice, i.status
    from inserted i join
         deleted d
         on i.requestid = d.requestid
    where i.assignedtouser <> d.assignedtouser;

注意:您应该永远不会假设inserteddeleted只有一行,就像您的原始代码那样。当有人试图update多行时,这会失败。

您还应该在insert语句中明确包含列列表。因此. . .用于messages表中的列列表。

答案 1 :(得分:1)

我认为应该这样做:

USE [gatordata]
GO
/****** Object:  Trigger [dbo].[TriggerUserAssigned] Script Date:2/20/2016 3:42:05 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[TriggerUserAssigned]
ON [dbo].[User]
AFTER UPDATE
AS
    INSERT  [Messages](
            [RequestID],        [AssignedToUser],   [TimeStamp],            [Hour],
            [RushService],      [Status],           [MessageText]) 
    SELECT 
            i.[Id],             i.[AssignedToUser], GETDATE(),              i.[Hour],
            i.[RushService],    i.[Status],         'New Critical Request'
    FROM    [inserted]  i
    JOIN    [deleted]   d       ON d.[Id] = i.[Id] 
    WHERE   d.[AssignedToUser] <> i.[AssignedToUser];
GO

通过将inserted表连接到已删除的表,您应该能够比较该列中的值以确定它是否已更改。额外的好处是您可以直接从插入的表中选择,而不必将所有内容分配给变量。