继承了一些工作并创建了一个触发器。根据我所读过的内容,我已经完成了我不应该做的事情(声明变量等),但触发器只适用于影响一行的更新。如果更新影响多行,则会失败。
基本上,触发器存储已删除的旧/上一个'从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
从我的搜索中我发现每个语句触发一次触发器,而不是每行受影响。我已经读过可以修改触发器以检查正在更新的行数,然后使用此信息根据每一行执行操作。不幸的是,我没有找到一种方法来理解这一点。
我的强项是网络前端编码,我的SQLServer编码有限。代码需要在SQL而不是前端,因为除了Web前端之外,还有一些其他工具可以更新这些记录。
任何有关调整此触发器的帮助,以便它也能在一个声明中处理多个更新,我们将不胜感激。
答案 0 :(得分:1)
这可能不是最佳选择,但解决此问题的一种方法是使用临时表来存储更改的机器,然后加入到已插入或已删除的表中。如:
ALTER TRIGGER [dbo].[tr_StatusChange_tblMachine] ON [dbo].[tblMachine]
AFTER UPDATE
AS BEGIN
SET XACT_ABORT ON;
SET NOCOUNT ON;
SET ROWCOUNT 0;
CREATE TABLE #tmp(MachineName nvarchar(50), NewStatus nvarchar(20) NULL, OldStatus nvarchar(20) NULL)
INSERT INTO #tmp(MachineName, NewStatus)
SELECT MachineName,MachineStatus from inserted
UPDATE #tmp SET OldStatus = d.MachineStatus
From deleted d
INNER JOIN #tmp t on t.MachineName = d.MachineName
---You could delete from #tmp where OldStatus is null to ensure this was an update
-- Status Changed
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 #tmp t
ON i.MachineName = t.MachineName and t.NewStatus <> t.OldStatus
WHERE i.SupportTeamID <> 'mbe' ;
-- 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 #tmp t
ON i.MachineName = t.MachineName and t.OldStatus = t.NewStatus
WHERE i.SupportTeamID <> 'mbe' And i.ServiceCheck <> d.ServiceCheck
AND (i.MachineStatus <> 'DecommissionedX' AND i.MachineStatus <> 'Dismantled');
END
再次,您需要检查语法,因为我只是修改您的代码,但这是这个想法的要点。
答案 1 :(得分:0)
我认为这样做了。诀窍是直接在插入到审计表中的插入和删除表中使用MachineStatus,而不是尝试预先计算通用的新旧状态。
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;
IF UPDATE (MachineStatus)
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, CONCAT(d.MachineStatus, '-', i.MachineStatus), i.ChangedBy
FROM inserted i JOIN deleted d
ON i.MachineName = d.MachineName
WHERE i.SupportTeamID <> 'mbe'
-- Status Changed
AND i.MachineStatus <> d.MachineStatus;
-- 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')
-- NO STATUS CHANGE
AND (i.MachineStatus = d.MachineStatus);
END;
END