You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL存储过程仅更新行一次问题排查(.NET Core+SSMS)

问题分析与解决方案

问题根源

SQL的UPDATE语句在单次执行时,同一目标行只会被更新一次——它会基于目标行的初始值,和关联的所有源数据进行计算,但不会像你预期的那样迭代更新。哪怕PedidosBorrados里有两行匹配记录,Inventory.Embarques的目标行只会用初始的TotalKilos和Percentage计算一次,不会先减第一行再减第二行。

解决方案

要实现逐步递减的效果,必须逐行处理PedidosBorrados的记录,每次更新都基于上一次更新后的最新值计算。以下是两种适配场景的方案:

方案1:游标逐行处理(严格按顺序更新)

如果业务要求必须按特定顺序逐步扣减重量,用游标是最直接的方式:

DECLARE @EmbarqueId INT, @Kilos DECIMAL(18,2)

-- 声明游标,获取待处理记录(可添加排序字段保证处理顺序)
DECLARE pedidos_cursor CURSOR FOR
SELECT EmbarqueId, Kilos
FROM dbo.PedidosBorrados
WHERE Actualizado = 0
ORDER BY -- 此处添加排序字段,比如创建时间或业务优先级字段

OPEN pedidos_cursor
FETCH NEXT FROM pedidos_cursor INTO @EmbarqueId, @Kilos

WHILE @@FETCH_STATUS = 0
BEGIN
    -- 基于当前最新值更新Embarques
    UPDATE Inventory.Embarques
    SET Percentage = ((TotalKilos - @Kilos) * Percentage) / TotalKilos,
        TotalKilos = TotalKilos - @Kilos
    WHERE EmbarqueId = @EmbarqueId

    -- 标记当前记录为已处理,避免重复操作
    UPDATE dbo.PedidosBorrados
    SET Actualizado = 1
    WHERE EmbarqueId = @EmbarqueId AND Kilos = @Kilos

    FETCH NEXT FROM pedidos_cursor INTO @EmbarqueId, @Kilos
END

CLOSE pedidos_cursor
DEALLOCATE pedidos_cursor

方案2:聚合更新(仅需最终结果)

如果业务不要求严格的逐步更新顺序,只需要最终重量是初始值减去所有待扣减的总和,可直接用聚合查询一次性更新:

UPDATE Inventory.Embarques 
SET Percentage = ((a.TotalKilos - b.TotalKilosToSubtract)*a.Percentage)/a.TotalKilos,
    TotalKilos = a.TotalKilos - b.TotalKilosToSubtract
From Inventory.Embarques a
INNER JOIN (
    SELECT EmbarqueId, SUM(Kilos) AS TotalKilosToSubtract
    FROM dbo.PedidosBorrados 
    WHERE Actualizado = 0
    GROUP BY EmbarqueId
) b 
ON  a.EmbarqueId = b.EmbarqueId

注意:此方案是直接用初始值扣除总和,和逐步递减的逻辑有差异——如果Percentage的计算依赖上一次更新后的结果,这个方案不适用。

关键提示

你之前的误区在于:SQL的UPDATE不会对同一行进行多次迭代更新,无论关联多少源数据,它都只会基于目标行的初始状态计算最终值。必须用循环或游标才能实现逐步更新的效果。

内容的提问来源于stack exchange,提问作者AhOkCasiCasiCasi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:35:29