【问题标题】:Delete Trigger with Update Subquery Statement with Multirow Delete使用多行删除的更新子查询语句删除触发器
【发布时间】:2021-02-01 21:56:48
【问题描述】:

这个触发器在单行删除时工作正常,但在多行上

CREATE TRIGGER [dbo].[AfterDeleteStockUpdate] 
ON [dbo].[ItemLedger]
AFTER DELETE
AS 
    DECLARE @productId uniqueidentifier

    SELECT @productId = del.Product 
    FROM deleted del;

    UPDATE products 
    SET inStock = (SELECT SUM(ISNULL(inQty, 0)) - SUM(ISNULL(outQty, 0)) 
                   FROM itemledger 
                   WHERE product = @productId), 
        PurchasedValue = (SELECT SUM(ISNULL(PurchaseAmount, 0)) - SUM(ISNULL(Amount, 0)) 
                          FROM itemledger 
                          WHERE product = @productId) 
    WHERE id = @productId

【问题讨论】:

  • 您的答案似乎可以解决您的主要问题。但它遵循了您尝试的模式,这是非常低效的。为什么效率低下?因为您将分类帐表中所有相关的现有行求和 - 绝对没有理由这样做。您应该做的是使用已删除的表来简单地更新受影响的产品。如果我们假设存在正确的外键,您对 ISNULL 的使用是不正确的,并且可能不需要。
  • 也许物化视图可能是更好的解决方案?这将自动调整分类帐中的更改,而无需任何触发代码。

标签: sql sql-server tsql triggers


【解决方案1】:

Deleted 伪表中可以有 0-N 行,您需要处理这些行。和所有 T-SQL 一样,您希望尽可能使用完全基于集合的方法,因为这就是 SQL Server 的优化目标。

我相信以下内容应该可以实现您想要的。

CREATE TRIGGER [dbo].[AfterDeleteStockUpdate] 
ON [dbo].[ItemLedger]
AFTER DELETE
AS
BEGIN
    SET NOCOUNT ON;

    UPDATE P SET
      inStock = L.inStock
      , PurchasedValue = L.PurchasedValue
    FROM Products P
    INNER JOIN (
        SELECT SUM(ISNULL(L.inQty, 0)) - SUM(ISNULL(L.outQty, 0)) inStock
            , SUM(ISNULL(L.PurchaseAmount, 0)) - SUM(ISNULL(L.Amount, 0)) PruchasedValue
        FROM itemledger L
        GROUP BY L.product
    ) L ON L.product = P.id
    WHERE P.id IN (SELECT Product from Deleted);

END;

【讨论】:

  • @hsn 这回答了你的问题吗?
  • 我已经使用 fetch/cursor 来解决我的问题,我会尝试这种方法并相应地更新您
  • @hsn - 如果可能的话,您当然希望避免在触发器中使用游标,
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-11
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-03
相关资源
最近更新 更多