【发布时间】:2020-07-27 10:30:17
【问题描述】:
我的触发器有问题,当我在另一个表中有新行时应该更新一个表。
我有两张桌子:
第一:
SELECT
[Id], [Timestamp], [MachineName], [StatusId], [Quantity]
FROM [dbo].[Events]
第二个:
SELECT
[Id], [MachineName], [StatusId], [QuantitySum], [StatusLastRefresh]
FROM [dbo].[ActualParams]
到表 [Events] 会处理来自流分析的每台机器上的所有状态更改。对于每一个新行,第二个表都应该更新并显示每台机器的最后一个值,最后一个时间戳在 StatusLastRefresh 中。实际上表[ActualParams]有4行数据。
我已经尝试了 2 个触发器来这样做:
ALTER TRIGGER [dbo].[AfterInsertEvent]
ON [dbo].[Events]
AFTER INSERT
AS
MERGE ActualParams AS ap
USING (SELECT Id, Machine, Status, Timestamp, Quantity
FROM inserted) AS ev ON ev.MachineName = ap.MachineName
WHEN MATCHED THEN
UPDATE SET map.StatusId = ev.StatusId,
ap.StatusLastRefresh = ev.Timestamp,
ap.QuantitySum = ap.QuantitySum + ev.Quantity;
触发器 #2:
ALTER TRIGGER [dbo].[AfterInsertEvent]
ON [dbo].[Events]
AFTER INSERT
BEGIN
DECLARE @mn nchar(10), @si int, @ts datetime2(7), @q int
SELECT @mn = MachineName, @si = StatusId, @ts = Timestamp, @q = Quantity
FROM inserted
UPDATE ActualParams
SET StatusId = @si,
StatusLastRefresh = @ts,
QuantitySum = QuantitySum + @q
WHERE ActualParams.MachineName = @mn
END
但它们都不能 100% 正确工作。
首先,Merge 触发器在每个 MachineName 同时插入一个行时可以正常工作,但有时对于同一 MachineName 插入的新行很少同时出现,我收到错误它不能同时将多行写入一个并且一切都卡住了。
其次,更简单的Update 触发器有时会跳过一行,并且在 ActualParams 表中有先前的 StatusId 值,而不是实际值。实际上我有 4 台机器,通常其中一台的 StatusId 错误。我想知道当有 20 台或更多机器时会发生什么。
MachineName 对于每台机器都是唯一的。
我用 UPDATE 尝试了 CURSOR,但有时仍会跳过该行,并且状态不是实际的。
我不知道如何将 CURSOR 与 MERGE 结合起来,也许这将是解决方案。
它必须对每一行做出反应,因为我还想在第二个表中汇总数量,所以这就是为什么我不能跳过任何行(之前忘记了 - 已编辑)
有什么想法吗?我正在使用 SSMS 17。
【问题讨论】:
-
您使用的是哪个 dbms?
-
@jarlh 我正在使用 SSMS
-
最重要的是:AVOID 触发器内的游标 不惜一切代价! 游标很糟糕、很慢,而且几乎没有需要 - 触发器应该非常小、灵活和快速 - NOT 混合使用这两者!你可以给自己带来的最糟糕的性能噩梦......
标签: sql-server tsql database-trigger sql-merge