6

这是一个非常简单的问题,但 SQL Server 文档并没有像我希望的那样清楚地解释这一点,所以我希望有人能帮我解释清楚。

我正在使用基于电子表格的新值更新表 - 这意味着我UPDATE在单个查询中使用多个语句:

UPDATE Asset SET AssetID = 'NewID' WHERE AssetID = 'OldID'

这是基本查询,但是用实际 ID 号代替 NewID 和 OldID,所以整个查询看起来很像这样;

UPDATE Asset SET AssetID = '001' WHERE AssetID = '111'
UPDATE Asset SET AssetID = '002' WHERE AssetID = '112'
UPDATE Asset SET AssetID = '003' WHERE AssetID = '113'

我担心遇到的问题是,在某些情况下,根据 SQL 更新这些字段的顺序以及它在WHERE子句中使用的值,我可能最终会无意中更新多行。

例如:

UPDATE Asset SET AssetID = '001' WHERE AssetID = '111'
UPDATE Asset SET AssetID = '002' WHERE AssetID = '001'
UPDATE Asset SET AssetID = '003' WHERE AssetID = '002'

现在想象一下,在我运行上述查询之前,我有下表:

AssetID
111
001
002

我想要发生的是,对于WHERE我的UPDATE语句中的子句,仅使用CURRENTLYAssetID列具有的 - 即在运行查询之前使用的。ID

这会给我下表:

AssetID
001
002
003

我担心实际上会发生,它会按顺序处理更新,并IDWHERE子句中使用更新,这意味着我的表将如下所示:

AssetID
003
003
003

现在,在我对此进行研究的过程中,我设法找到了一些关于 SQL Server 如何处理此问题的文档——即它使用了 UPDATED 值。它指出这种行为与“普通 SQL”处理它的方式不同,所以我希望在使用 SQL Server 时这不会成为问题。

有人可以确认吗?

4

1 回答 1

19

这是万圣节问题的一个表现。
由于更新的应用方式(尤其是唯一性),您还可能会遇到约束错误

一次进行多次更新以避免中间错误的方法是进行一次更新

UPDATE
    A
SET
    A.AssetID = N.NewAssetID
FROM
   Asset A
   JOIN
   SomeTempTableOrTableVar N ON A.AssetID = OldAssetId 

SomeTempTableOrTableVar 是一个表值参数、临时表或 values 子句的表变量,有 2 列

编辑:或根据 OP 的评论使用额外的列。

例子

UPDATE Asset SET AssetID = '001' WHERE AssetID = '111'
UPDATE Asset SET AssetID = '002' WHERE AssetID = '001'
UPDATE Asset SET AssetID = '003' WHERE AssetID = '002'

...变成这样:

UPDATE
    A
SET
    A.AssetID = N.NewAssetID
FROM
   Asset A
   JOIN
   (VALUES
      ('111', '001'),
      ('001', '002'),
      ('002', '003')
   ) N (OldAssetId, NewAssetID) ON A.AssetID = OldAssetId 
于 2013-05-16T14:18:57.017 回答