2010-08-13 60 views
6

请考虑这个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

回答

8

号单UPDATE语句原子,他们各自的部分没有秩序。

这两种:

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根本不必关心并发性。它绝对不会锁定任何东西,只需遍历每个相关行,进行更改即可。

+0

读取和写入都发生在同一时间吗?它不会在sql server的工作方式上创建任何并发性吗? – IsmailS 2010-08-13 08:26:10

+0

+1谢谢...... – IsmailS 2010-08-14 11:50:56

3

SQL不按字段顺序评估值。就SQL而言,这些陈述是相同的。

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

什么情况是,SQL访问的每个行的表,然后在同一时间更新AB当前更新B为0

如果它可以帮助你理解,您可以将其视为更新触发器中发生的情况,该更新触发器可以访问DELETED逻辑表中的表的当前值以及INSERTED逻辑表中的新值。

+0

读取和写入都发生在同一时间吗?它不会在sql server的工作方式上创建任何并发性吗? – IsmailS 2010-08-13 08:25:26

+0

你没有阅读。你正在写作。 – Oded 2010-08-13 08:25:46

+0

如果你观察到我正在阅读'B'的值并将其设置为'A'的语句。 – IsmailS 2010-08-13 08:57:06

0

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

所以此值被设置为A柱从DELETED表的B柱并且被设置为0是一个在INSERTED表中的值B检索。

2

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

有用的备忘录是

UPDATE MyTable 
    SET A = B, B = A; 

将转置的列的值。

+0

+1谢谢...... – IsmailS 2010-08-14 11:50:38