SQL Server:在单个查询中使用多个UPDATES时,WHERE子句是否会使用当前或更新的字段值?

Jed*_*abe 5 sql-server sql-server-2008 sql-update

这是一个非常简单的问题,但SQL Server文档没有像我想的那样清楚地解释这个问题,所以我很感激有人为我拼写出来.

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

UPDATE Asset SET AssetID = 'NewID' WHERE AssetID = 'OldID'
Run Code Online (Sandbox Code Playgroud)

这是基本的查询,但用实际的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'
Run Code Online (Sandbox Code Playgroud)

我担心遇到的问题是,可能存在某些情况,根据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'
Run Code Online (Sandbox Code Playgroud)

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

AssetID
111
001
002
Run Code Online (Sandbox Code Playgroud)

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

这会给我下表:

AssetID
001
002
003
Run Code Online (Sandbox Code Playgroud)

我很担心会ACTUALLY发生,是它会顺序处理更新,并使用更新ID的的WHERE条款,这意味着我的表反而会是这样的:

AssetID
003
003
003
Run Code Online (Sandbox Code Playgroud)

现在,在我对此进行研究的过程中,我设法找到了一些关于SQL Server如何处理这个问题的文档 - 它使用了UPDATED值.它声明此行为与"Normal SQL"处理它的方式不同,所以我希望在使用SQL Server时这不会成为问题.

有人可以证实吗?

gbn*_*gbn 17

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

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

UPDATE
    A
SET
    A.AssetID = N.NewAssetID
FROM
   Asset A
   JOIN
   SomeTempTableOrTableVar N ON A.AssetID = OldAssetId 
Run Code Online (Sandbox Code Playgroud)

SomeTempTableOrTableVar是一个tablevalued参数,临时表或包含2列的values子句的表变量

编辑:或根据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'
Run Code Online (Sandbox Code Playgroud)

......变成这个:

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 
Run Code Online (Sandbox Code Playgroud)