我遇到了一个让我感到困惑的SQL Server触发器间歇性错误,因为似乎我正在做所有正确的事情来防止错误发生。我收到的错误是“触发器返回了一个结果集和/或正在运行SET NOCOUNT OFF,而另一个未完成的结果集处于活动状态。”我已经进行了网络搜索,发现一些适用于触发器的东西,我认为可以解决该问题,但似乎没有做到。这是一个很少发生的问题,但足以成为一个问题。不过,我还不能说为什么会这样。这是此触发器的示例:
CREATE TRIGGER [dbo].[trgAppointmentLogDispatch] ON [dbo].[Appointment] FOR INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON
IF EXISTS (SELECT 1 FROM inserted) BEGIN
INSERT INTO DispatchQueue (ObjectType, CompanyID, KeyField1, KeyField2, KeyField3, KeyField4, KeyField5, Deleted, DateChanged)
SELECT 'Appointment', ISNULL(i.CompanyID, 0), ISNULL(i.OrderID, -1), ISNULL(i.AppointmentID, -1), NULL, NULL, NULL, 0, GETUTCDATE()
FROM inserted i
LEFT JOIN deleted d
ON i.AppointmentID = d.AppointmentID
WHERE ISNULL(i.Field1, '') <> ISNULL(d.Field1, '')
OR ISNULL(i.Field2, '') <> ISNULL(d.Field2, '')
OR ISNULL(i.Field3, 0) <> ISNULL(d.Field3, 0)
OR ISNULL(i.Field4, '1/1/2000') <> ISNULL(d.Field4, '1/1/2000')
OR ISNULL(i.Field5, '1/1/2000') <> ISNULL(d.Field5, '1/1/2000')
OR ISNULL(i.Field6, 0) <> ISNULL(d.Field6, 0)
OR ISNULL(i.Field7, '') <> ISNULL(d.Field7, '')
OR ISNULL(i.Field8, '') <> ISNULL(d.Field8, '')
END ELSE BEGIN
INSERT INTO DispatchQueue (ObjectType, CompanyID, KeyField1, KeyField2, KeyField3, KeyField4, KeyField5, Deleted, DateChanged)
SELECT 'Appointment', ISNULL(CompanyID, 0), ISNULL(OrderID, -1), ISNULL(AppointmentID, -1), NULL, NULL, NULL, 1, GETUTCDATE()
FROM deleted
END
SET NOCOUNT OFF
END
GO
触发器执行的所有操作是侦听名为“约会”的表上一组字段的更改(或侦听此表中记录的删除)。如果删除或更改了WHERE子句中正在检查的字段,它将在DispatchQueue表中插入一条新记录,该表将由与该问题无关的单独进程使用。
在以前寻找该问题的解决方案时,我普遍认为可以解决该问题的共识是将SET NOCOUNT ON命令添加到触发器的开头,并添加SET NOCOUNT OFF命令到我的触发器的最后一行。但是,在这种情况下,这种方法不起作用,所以我对下一步的工作感到困惑。
是否可以在最后删除SET NOCOUNT OFF命令来解决此问题?我想知道是否可以,因为在显示问题发生的SQL跟踪中,在运行SET NOCOUNT OFF语句后立即报告了错误。如果是这样,那还会带来其他潜在问题吗?看来我的触发器似乎没有返回结果集(它只是运行EXISTS语句来检查并查看我是在处理插入还是删除操作,然后运行INSERT语句以将数据插入到另一个表中),但是可能会在我看不见或不了解的某个地方(或以某种方式)这样做吗?
我的触发器之外的数据库中发生的其他事情是否会导致在运行时报告此问题?
我感谢所有见解。请让我知道是否可以提供任何进一步的信息。