在同一个表中使用其他值更新一列

时间:2010-08-13 08:18:38

标签: sql sql-server tsql

请考虑这个sql语句

Create table abc 
(A int,
B int
)

insert into abc values (1,2)

以下两个陈述都做同样的事情。为什么呢?

update abc 
set A = B,
B =0
where A=1

update abc 
set B =0,
A = B
where A=1

我原以为在后面的语句中B列首先设置了值,然后将A列'的值设置为B's

4 个答案:

答案 0 :(得分:8)

没有。单个更新语句是原子的,各个部分没有顺序。

这两个:

update abc set A = B, B = 0 where A=1
update abc set B = 0, A = B where A=1

完全同样的事情,因为这两项任务被认为是同时发生的。

换句话说,B右侧的=B的旧值。


附录:如何 DBMS实现此行为取决于编写DBMS的人员的聪明才智。

例如,DBMS 可能会尝试锁定A为1的所有行,一旦完成,请执行A = BB = 0 (按顺序,因为执行引擎认为这将满足并发性,在更改A之前将B设置为B)。

set A = B, B = A之类的语句需要更多的智能,但它可以通过先保存当前行并使用其中的值来设置新行中的值来轻松实现,例如:

read in oldrow
copy oldrow to newrow
newrow.A = oldrow.B
newrow.B = oldrow.A
write out newrow

然后它将解锁所有行。

这只是一个选择。一个非常愚蠢的DBMS可能只是锁定整个数据库文件,尽管这不会产生非常智能的并发。

单用户,单线程DBMS根本不必关心并发性。它绝对没有锁定,只是通过每个相关的行,进行更改。

答案 1 :(得分:3)

SQL不按字段顺序评估值。就SQL而言,语句是相同的。

更新发生在一个步骤(原子),而不是几个有序的。

SQL会访问表中的每一行,然后将A同时更新为B当前 >将B更新为0。

如果它有助于您理解,您可以将其视为更新触发器中发生的事情,该触发器可以访问DELETED逻辑表中表的当前值以及{{中的新值1}}逻辑表。

答案 2 :(得分:2)

@Ismail回答的变化:从逻辑上讲,更新是一起提交的删除和插入,这就是为什么你在每个逻辑表deletedinserted中得到一行的原因分别。这里的工作单元是行:当一行更新时,它将被删除并使用新值重新插入(如果您想知道哪些值实际发生了变化,您必须自己解决这个问题) )。

有用的备忘录是

UPDATE MyTable
   SET A = B, B = A;

将转置列的值。

答案 3 :(得分:0)

现在我明白了,当我们运行Update语句时,有两个逻辑表,即DELETEDINSERTED

因此,从A表的B列检索设置为DELETED列的值,并且设置为0的B的值是INSERTED表。