我正在使用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朋友......
答案 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;
注意:您应该永远不会假设inserted
和deleted
只有一行,就像您的原始代码那样。当有人试图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表连接到已删除的表,您应该能够比较该列中的值以确定它是否已更改。额外的好处是您可以直接从插入的表中选择,而不必将所有内容分配给变量。