首页 > 解决方案 > 更新触发器未在 where 子句中使用日期,导致更新具有相同键 id 的所有记录,而不仅仅是具有当前日期的记录

问题描述

我有一个库存跟踪应用程序,我还跟踪每个位置的库存变化。库存项目可以在多个位置。这是通过拥有一个跟踪数据库并在我的库存表上使用触发器来实现的。如果我更改一次项目的数量,触发器将按预期工作。如果我返回并再次更改同一位置的数量,则该位置的所有数量(仅)都会更新为相同的数量。这是我的触发器:

INSERT tblInvTracking(keyProductID, fldLocationId, fldLastPhysical, fldQuantity, fldInventoryChange, fldNewQuantity)
    SELECT D.keyProductID, I.fldLocationID, D.fldLastPhysical, d.fldQuantity, i.fldLastPhysical, i.fldQuantity
    FROM DELETED D
    JOIN INSERTED I ON D.keyProductID = I.keyProductID
    WHERE D.fldLastPhysical <> i.fldLastPhysical AND d.fldLocationID = i.fldLocationID;

UPDATE tblInvTracking 
    SET fldNewQuantity = (SELECT inserted.fldQuantity FROM inserted)
    FROM deleted d
    JOIN inserted i ON D.keyProductID = I.keyProductID
    WHERE d.fldLastPhysical = i.fldLastPhysical AND tblInvTracking.keyProductID = i.keyProductID AND tblInvTracking.fldLocationID = i.fldLocationID;

由于我的 INSERT 语句正确执行,我知道 WHERE 子句有效。问题必须出在我的 UPDATE WHERE 子句中,该子句似乎忽略了 d.fldLastPhysical = i.fldLastPhyiscal。

注意:触发器是我的库存表的“ON UPDATE”触发器。当我在特定日期更改特定位置的特定零件的数量时,触发器将在跟踪表中插入一条新记录。如果数量随后发生变化,则在该日期该位置的该零件上不会创建新记录。这就是 where 子句在 insert 语句中所做的并且有效。

我想要发生的是,如果在同一地点的同一日期更改数量,则跟踪表中的数量将在该日期更新。似乎 D.fldLastPhysical <> i.fldLastPhysical 有效,但 d.fldLastPhysical = i.fldlastPhysical 无效。针对所有日期更新特定位置的单个部分。

如果不清楚,我很抱歉,但我必须了解您的回复并处理结果。因此,更新语句中的 where 子句无法正常工作。

谢谢

标签: c#triggerssql-server-2019-express

解决方案


你犯了一个典型的错误——假设触发器Inserted中的伪表UPDATE只包含一行——通常情况并非如此!

看看这段代码:

UPDATE tblInvTracking 
SET fldNewQuantity = (SELECT inserted.fldQuantity FROM inserted)
                     ********************************************
FROM deleted d
JOIN inserted i ON D.keyProductID = I.keyProductID

如果您的UPDATE操作影响 10 行 - 您认为其中哪一行将用于获取inserted.fldQuantity值?它是不确定的- 将使用一个,忽略所有其他。这是双重可悲的,因为您已经在以适当的、基于集合的方式访问Inserted和查询。Deleted

那你为什么不直接用这个??

UPDATE it
SET fldNewQuantity = i.fldQuantity 
FROM inserted i 
INNER JOIN tblInvTracking it ON it.keyProductID = i.keyProductID 
                             AND it.fldLocationID = i.fldLocationID;

既然您没有引用Deleted伪表中的任何内容-为什么还要将其包含在UPDATE? 另外:定义和之间的连接条件,Inserted而不是用一个tblInvTracking子句......INNER JOINWHERE


推荐阅读