使用子查询更新 - 更新超过所需记录

时间:2013-07-23 13:16:36

标签: sql sql-server

大家好日子。我想问一个关于我的SQL语句的问题。我使用的是SQL Server 2008,并且有一个名为Workflow Transaction的表。在这张表中,我有12条记录。下图是表格的内容。

enter image description here

我有这个SQL语句:

UPDATE Workflow_Txn 
SET Status = 1
WHERE [RequestId] IN
(
    SELECT [RequestId]
    FROM Workflow_Txn 
    WHERE [OrderNumber] < (SELECT MAX(OrderNumber) FROM Workflow_Txn WHERE RequestId = 3)      
    AND RequestId = 3
)

我的目标是更新OrderNumber小于最大值的请求ID,它将是WHERE子句中SELECT语句的输出。现在我希望更新的记录只应是所述记录(在代码中,它是RequestId#3)。

实际发生的事情不是只更新了四条记录,而是五(5)条!我现有的SQL语句有问题吗?

3 个答案:

答案 0 :(得分:6)

您的问题是您正在使用RequestId = 3对所有记录进行更新。请考虑您的子查询结果为3,以便最终更新所有相关记录。

您的查询等同于执行

UPDATE Workflow_Txn 
SET Status = 1
WHERE RequestId = 3

不确定您是否有任何理由让您的查询更加复杂。在我看来,更简单的事情可以解决这个问题

UPDATE Workflow_Txn 
SET    Status = 1
WHERE  [OrderNumber] < (SELECT MAX(OrderNumber) FROM Workflow_Txn WHERE RequestId = 3)      
       AND RequestId = 3

答案 1 :(得分:6)

您的查询的问题在于子查询非常详细地查找订单号小于最大值的记录。然后它选择具有相同请求的所有内容 - 其中包括最大订单号。

我更喜欢使用CTE解决这个问题,如下所示:

with toupdate as (
      select t.*,
             MAX(OrderNumber) as MaxON
      from Workflow_txn
      where RequestId = 3
     )
UPDATE toupdate
    SET Status = 1
    where OrderNumber < MaxON;

我喜欢这种结构,因为我可以单独运行CTE来查看哪些记录可能会更新。

要修复您的查询,您可以将请求更改为使用OrderNumber并重复RequestId = 3

UPDATE Workflow_Txn 
SET Status = 1
WHERE [RequestId] = 3 and
      OrderNumber in
(
    SELECT [OrderNumber]
    FROM Workflow_Txn 
    WHERE [OrderNumber] < (SELECT MAX(OrderNumber) FROM Workflow_Txn WHERE RequestId = 3)      
    AND RequestId = 3
)

答案 2 :(得分:4)

您的子查询只是说要返回RequestID为3,所以您使用该ID更新了所有请求;走过去。我认为你在寻找的是:

UPDATE Workflow_Txn 
SET Status = 1
WHERE [RequestId] = 3
AND  [OrderNumber] < (SELECT MAX(OrderNumber) FROM Workflow_Txn WHERE RequestId = 3)