【发布时间】:2017-07-12 22:54:25
【问题描述】:
继承了一些工作并创建了触发器。从我读过的内容来看,我做了我不应该做的事情(声明的变量等),但触发器适用于只影响一行的更新。如果更新影响多行,则会失败。
基本上,触发器将 tblMachine 中特定字段的“已删除旧/以前”值存储到 tblAudit 中。
我的触发器是...
USE [MyDB]
GO
/****** Object: Trigger [dbo].[tr_StatusChange_tblMachine] Script Date: 12/07/2017 09:00:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[tr_StatusChange_tblMachine] ON [dbo].[tblMachine]
AFTER UPDATE
AS BEGIN
SET XACT_ABORT ON;
SET NOCOUNT ON;
SET ROWCOUNT 0;
DECLARE @NewStatus nvarchar(20);
DECLARE @OldStatus nvarchar(20);
DECLARE @ChangeMade nvarchar(50);
IF UPDATE (MachineStatus)
BEGIN
SET @NewStatus = (SELECT i.MachineStatus FROM inserted i FULL OUTER JOIN deleted d ON i.ID = d.ID);
SET @OldStatus = (SELECT d.MachineStatus FROM deleted d FULL OUTER JOIN inserted i ON i.ID = d.ID);
SET @ChangeMade = CONCAT ( @OldStatus, '-', @NewStatus );
-- Status Changed
IF @OldStatus <> @NewStatus
BEGIN
INSERT INTO dbo.tblAudit (InsertedDate, Month, Year, SupportTeam, MachineName, MachineStatus,
DateBuilt, DismantledDate, ServiceCheck, ServiceCheckBit, ChangeMade, ChangedBy)
SELECT getdate() AS InsertedDate ,(datepart(month,getdate())) AS Month, (datepart(Year,getdate())) AS Year,
i.SupportTeam, i.MachineName, i.MachineStatus, i.DateBuilt, i.DismantledDate,
CASE i.ServiceCheck WHEN 0 THEN 'No' ELSE 'Yes' END AS ServiceCheck, i.ServiceCheck, @ChangeMade, i.ChangedBy
FROM inserted i JOIN deleted d
ON i.MachineName = d.MachineName
WHERE i.SupportTeamID <> 'mbe';
END;
-- NO STATUS CHANGE
IF @OldStatus = @NewStatus
BEGIN
-- NO STATUS CHANGE
-- Service Check may have changed!
-- INSERT INTO AUDIT IF ServiceCheck has changed AND MachineStatus is NOT DecommissionedX or Dismantled.
INSERT INTO dbo.tblAudit (InsertedDate, Month, Year, SupportTeam, MachineName, MachineStatus,
DateBuilt, DismantledDate, ServiceCheck, ServiceCheckBit, ChangeMade, ChangedBy)
SELECT getdate() AS InsertedDate, (datepart(month,getdate())) AS Month, (datepart(Year,getdate())) AS Year,
i.SupportTeam, i.MachineName, i.MachineStatus, i.DateBuilt, (SELECT getdate() AS DismantledDate),
CASE i.ServiceCheck WHEN 0 THEN 'No' ELSE 'Yes' END AS ServiceCheck, i.ServiceCheck, 'SC Changed - Status Not Changed', i.ChangedBy
FROM inserted i JOIN deleted d
ON i.MachineName = d.MachineName
WHERE i.SupportTeamID <> 'mbe' And i.ServiceCheck <> d.ServiceCheck
AND (i.MachineStatus <> 'DecommissionedX' AND i.MachineStatus <> 'Dismantled');
END;
END;
END
从我的搜索中,我发现触发器每条语句触发一次,而不是每行受影响。我读过可以修改触发器以检查正在更新的行数,然后使用此信息根据每一行执行操作。不幸的是,我还没有找到一种我理解的方法。
我的强项是 Web 前端编码,而我的 SQLServer 编码有限。代码需要在 SQL 中,而不是在前端,因为除了 Web 前端之外,还有一些其他工具可以更新这些记录。
任何帮助调整此触发器以便它也可以在一个语句中处理多个更新将不胜感激。
【问题讨论】:
-
您的搜索应该已经出现了大量示例。您是否有关于他们的更具体、更集中的问题,听起来不像是在试图让某人免费为您工作?
-
我的搜索完成了,但我理解的程度不足以实现。有些人正在使用我读过的光标可以达到性能。
-
SET XACT_ABORT 开启了怎么办?如果出现错误,这将取消事务中的所有剩余语句。我没有看到事务或错误处理。
-
@benjaminmoskovits 这证明我有一些 SQL 知识。这来自我找到并改编的基本代码...我会研究这个并删除或添加一些错误处理...谢谢
-
这需要一点时间,但通过 Sommarskog 的错误处理和事务处理工作确实值得。 sommarskog.se/error_handling/Part1.html。您将更多地了解 TSQL,并更接近成为一名真正的专业人士。
标签: sql-server triggers