请考虑这个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
值
答案 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 = B
,B = 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回答的变化:从逻辑上讲,更新是一起提交的删除和插入,这就是为什么你在每个逻辑表deleted
和inserted
中得到一行的原因分别。这里的工作单元是行:当一行更新时,它将被删除并使用新值重新插入(如果您想知道哪些列值实际发生了变化,您必须自己解决这个问题) )。
有用的备忘录是
UPDATE MyTable
SET A = B, B = A;
将转置列的值。
答案 3 :(得分:0)
现在我明白了,当我们运行Update语句时,有两个逻辑表,即DELETED
和INSERTED
。
因此,从A
表的B
列检索设置为DELETED
列的值,并且设置为0的B
的值是INSERTED
表。