带有内部联接的 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 更新的主要内容,如果未能解决你的问题,请参考以下文章

带有内部联接的 SQL 更新查询语法

带有 2 个内部联接的 SQL Server 2014 STUFF

带有内部联接的 Oracle 更新语句

SQL Server 2005 - 内部联接的顺序

SQL Server-交叉联接内部联接基础回顾

带有内部联接的 SQL 插入试图插入错误的列