我遇到了一个让我难过的 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
触发器所做的只是监听对名为 Appointment 的表上的一组字段的更改(或删除此表中的记录)。如果在 WHERE 子句中检查的字段有删除或更改,它将向 DispatchQueue 表中插入一条新记录,该表由与此处的问题无关的单独进程使用。
之前在寻找此问题的解决方案时,我得出的普遍共识是,将 SET NOCOUNT ON 命令添加到触发器的开头并将 SET NOCOUNT OFF 命令添加到最后我的触发器线。不过,在这种情况下这不起作用,所以我不知道下一步该往哪里看。
最后删除 SET NOCOUNT OFF 命令会解决问题吗?我想知道它是否可能,因为在显示问题正在发生的 SQL 跟踪中,在运行 SET NOCOUNT OFF 语句后立即报告了错误。如果是这样,那会带来任何其他潜在问题吗?我的触发器似乎没有返回一个结果集(它只是运行一个 EXISTS 语句来检查我是否正在处理插入或删除,然后它运行一个 INSERT 语句将数据插入另一个表),但是它可能会在我没有看到或理解的某个地方(或以某种方式)这样做吗?
我的触发器之外的数据库中发生的其他事情是否会导致在运行时报告此问题?
我感谢任何和所有的洞察力。请让我知道我是否可以提供有关此的任何进一步信息。