我们在更新期间触发的表上有一个触发器。我们在前端使用Entity Framework。因此,我们不希望在进行更新时看到中间结果(触发器的结果)。我在触发器中设置了NOCOUNT:
ALTER TRIGGER [dbo].[trgForMedCMDWorkItemsUpdate]
ON [dbo].[MedCMDWorkItems]
AFTER UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
但是当我们执行更新时,我们首先看到中间结果,然后抛出实体框架。
这是sql命令:
Declare @UserID int
set @UserID = 26
declare @WorkItemID int
Declare @UserRoles TABLE ( roleid INT ,parentroleid INT ,rolename VARCHAR(100) )
INSERT INTO @UserRoles SELECT R.id,R.parentroleid,R.ROLE FROM userroles UR
INNER JOIN roles R ON UR.roleid = R.id WHERE UR.userid = @UserID
Update MedCMDWorkItems with (UPDLOCK) Set AssignedTo = @UserID, AssignedAt =
getdate(), LastUpdatedAt = getdate(), LastUpdatedBy = @UserID, @WorkItemID =
ID
where ID = (SELECT TOP 1 PR.ID FROM MedCMDWorkItems PR --with (UPDLOCK)
JOIN TaskTypes TT on PR.TaskTypeID = TT.ID WHERE PR.AssignedTo IS NULL AND
PR.ClosedAt IS NULL
AND Exists (SELECT 1 FROM @UserRoles WHERE roleid in (852,772)) AND
((PR.WorkItemTypeID = (select 29 FROM @UserRoles UR WHERE UR.RoleID = 852)
AND TT.Task in (SELECT Substring(UR1.rolename, Charindex('|', UR1.rolename)
+ 1, Len(UR1.rolename)) FROM @UserRoles UR1 WHERE UR1.parentroleid in (852))
) OR
(PR.WorkItemTypeID = (select 28 FROM @UserRoles UR WHERE UR.RoleID = 772)
AND TT.Task in (SELECT Substring(UR1.rolename, Charindex('|', UR1.rolename)
+ 1, Len(UR1.rolename)) FROM @UserRoles UR1 WHERE UR1.parentroleid in (772))
) )
ORDER BY (CASE WHEN PR.IsUrgent IS NULL THEN 'False' ELSE PR.IsUrgent END)
DESC, ( CASE WHEN PR.Priority IS NULL THEN 9999 ELSE PR.Priority END ),
PR.CreatedAt)
Select * From MedCMDWorkItems PRI Where ID = @WorkItemID
这是触发器:
USE [CombinedWorkflow]
GO
/****** Object: Trigger [dbo].[trgForMedCMDWorkItemsUpdate] Script Date:
4/3/2018 5:20:22 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[trgForMedCMDWorkItemsUpdate]
ON [dbo].[MedCMDWorkItems]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
declare @NewAssignedAt DateTime;
declare @OldAssignedAt DateTime;
declare @NewPulledAt DateTime;
declare @ID int;
select @NewPulledAt = i.PulledAt from inserted i;
select @NewAssignedAt = i.AssignedAt from inserted i;
select @OldAssignedAt = d.AssignedAt from deleted d;
select @ID = i.ID from inserted i;
--If work item is being un-assigned
if(@OldAssignedAt is NOT NULL and @NewAssignedAt is NULL)
BEGIN
SET NOCOUNT ON;
Update MedCMDWorkItems
Set PulledAt = NULL
Where ID = @ID
END
--if work item is being assinged
ELSE if(@NewAssignedAt IS NOT NULL)
BEGIN
SET NOCOUNT ON;
Update MedCMDWorkItems
Set FirstAssignedAt = @NewAssignedAt
Where FirstAssignedAt is NULL and ID = @ID
END
-- if work item is being pulled
ELSE if(@NewPulledAt IS NOT NULL)
BEGIN
SET NOCOUNT ON;
Update MedCMDWorkItems
Set AssignedAt = @NewPulledAt
Where AssignedAt is NULL and ID = @ID
SET NOCOUNT ON;
Update MedCMDWorkItems
Set FirstAssignedAt = @NewPulledAt
Where FirstAssignedAt is NULL and ID = @ID
END
Select 1
END
当我在SSMS中执行触发器结果时,我得到2个结果,首先表示1行已更新,然后是第二个表示查询结果。
如果我禁用触发器并执行命令,我不会得到第一个结果,这是我在启用触发器时所需的行为。
如何设置此触发器以使其触发但不会导致其他结果?
谢谢, 萨默尔
答案 0 :(得分:0)
您需要使用inserted
和deleted
作为表,它们可以包含多行,因此您永远无法从中填充变量。
相反,你必须像这个例子一样构建它:
您的代码(第一部分)
ALTER TRIGGER [dbo].[trgForMedCMDWorkItemsUpdate]
ON [dbo].[MedCMDWorkItems]
AFTER UPDATE AS
BEGIN
SET NOCOUNT ON;
declare @NewAssignedAt DateTime;
declare @OldAssignedAt DateTime;
declare @NewPulledAt DateTime;
declare @ID int;
select @NewPulledAt = i.PulledAt from inserted i;
select @NewAssignedAt = i.AssignedAt from inserted i;
select @OldAssignedAt = d.AssignedAt from deleted d;
select @ID = i.ID from inserted i;
--If work item is being un-assigned
if(@OldAssignedAt is NOT NULL and @NewAssignedAt is NULL)
BEGIN
SET NOCOUNT ON;
Update MedCMDWorkItems
Set PulledAt = NULL
Where ID = @ID
END
可以被这样的东西取代(未经测试,因为我没有你的数据库)
ALTER TRIGGER [dbo].[trgForMedCMDWorkItemsUpdate]
ON [dbo].[MedCMDWorkItems]
AFTER UPDATE AS
BEGIN
SET NOCOUNT ON;
update MedCMDWorkItems
Set PulledAt = NULL
where ID in ( select i.Id
from Inserted i
left join deleted d on i.Id = d.Id
where d.AssignedAt is not null
and i.AssignedAt is null
)
一旦你得到这个,就不会很难弄清楚如何调整你的触发器的其余部分
答案 1 :(得分:0)
感谢大家的投入。我想出了这个问题。触发器在最后有这个:
... END
-- if work item is being pulled
ELSE if(@NewPulledAt IS NOT NULL)
BEGIN
SET NOCOUNT ON;
Update MedCMDWorkItems
Set AssignedAt = @NewPulledAt
Where AssignedAt is NULL and ID = @ID
SET NOCOUNT ON;
Update MedCMDWorkItems
Set FirstAssignedAt = @NewPulledAt
Where FirstAssignedAt is NULL and ID = @ID
END
Select 1
END
不知道最后一行(选择1)应该是什么(我没有写入触发器:)),但它导致显示不需要的结果。
萨默尔