带有内部联接的 SQL Server 更新
Posted
技术标签:
【中文标题】带有内部联接的 SQL Server 更新【英文标题】:SQL Server Update with Inner Join 【发布时间】:2011-03-28 22:27:18 【问题描述】:我有 3 张表(简化版):
tblOrder(OrderId INT)
tblVariety(VarietyId INT,Stock INT)
tblOrderItem(OrderId,VarietyId,Quantity INT)
如果我下订单,我会使用以下方式降低库存水平:
UPDATE tblVariety
SET tblVariety.Stock = tblVariety.Stock - tblOrderItem.Quantity
FROM tblVariety
INNER JOIN tblOrderItem ON tblVariety.VarietyId = tblOrderItem.VarietyId
INNER JOIN tblOrder ON tblOrderItem.OrderId = tblOrder.OrderId
WHERE tblOrder.OrderId = 1
一切正常,直到 tblOrderItem 中有两行具有相同的 VarietyId 用于相同的 OrderId。在这种情况下,只有其中一行用于库存更新。它似乎正在以某种方式在其中进行 GROUP BY VarietyId。
谁能解释一下?非常感谢。
【问题讨论】:
应该不可能有相同的品种/订单组合?也就是说,如果一个订单的同一个品种出现 >1,那么这被捕获在数量列中,而不是多行? 从技术上讲,是的。但是 tblOrderItem 中还有其他列,这意味着可以使用相同的基本数字(例如日期字段)进入多行 【参考方案1】:来自文档UPDATE
UPDATE 语句的结果是 如果语句包含一个未定义的 中未指定的 FROM 子句 这样只有一个值是 可用于每列出现 即被更新(换句话说,如果 UPDATE 语句不是 确定性)。例如,给定 下面的UPDATE语句 脚本,表 s 中的两行都满足 FROM 子句的限定条件 UPDATE 语句,但它是 未定义 s 中的哪一行用于 更新表 t 中的行。
CREATE TABLE s (ColA INT, ColB DECIMAL(10,3))
GO
CREATE TABLE t (ColA INT PRIMARY KEY, ColB DECIMAL(10,3))
GO
INSERT INTO s VALUES(1, 10.0)
INSERT INTO s VALUES(1, 20.0)
INSERT INTO t VALUES(1, 0.0)
GO
UPDATE t
SET t.ColB = t.ColB + s.ColB
FROM t INNER JOIN s ON (t.ColA = s.ColA)
GO
【讨论】:
【参考方案2】:我的猜测是,因为您向我们展示了简化的架构,所以缺少一些信息来确定为什么给定 OrderID 具有重复的 VarietyID 值。
当您有多行时,SQL Server 将任意选择其中一个进行更新。
如果是这种情况,你需要先分组
UPDATE V
SET
Stock = Stock - foo.SumQuantity
FROM
tblVariety V
JOIN
(SELECT SUM(Quantity) AS SumQuantity, VarietyID
FROM tblOrderItem
JOIN tblOrder ON tblOrderItem.OrderId = tblOrder.OrderId
WHERE tblOrder.OrderId = 1
GROUP BY VarietyID
) foo ON V.VarietyId = foo.VarietyId
如果不是,那么 OrderItems 表 PK 是错误的,因为如果允许重复的 OrderID/VarietyID 组合(PK 应该是 OrderID/VarietyID,或者这些应该是唯一的)
【讨论】:
【参考方案3】:您正在进行更新。它会更新一次。
编辑:要解决这个问题,您可以添加一个子查询,该子查询将按 orderid 和品种 ID 对您的订单项进行分组,并加上金额的总和。
【讨论】:
以上是关于带有内部联接的 SQL Server 更新的主要内容,如果未能解决你的问题,请参考以下文章