SQL UPDATE是否可传递?

时间:2013-06-24 15:28:40

标签: sql-server sql-update

Sql server是否阻止在以不同结果结尾的同一次执行中多次更新同一行?

如果一个表包含如下行:

1
2
3

并且有一个更新已经完成将所有'1'更改为'2'并且所有'2'更改为'3',是否可以将第一行更改为'2'然后再将其更改为'3'以结束为所有行都带有'3'值?

使用以下命令在SQL Server中进行测试:

create table t ( c1 int );
insert into t (c1) values (1);
insert into t (c1) values (2);
insert into t (c1) values (3);

update t
set c1 = 
    case 
        when c1 = 1 then 2 
        when c1 = 2 then 3 
        else c1 
    end
;

select * 
from t;

结果只为每个值提供一次逻辑更新。

但我正在考虑在这种情况下所有值都在同一页面中(因为它是一个小集合)。但是如果它们位于不同的页面中并且在更新期间使用一个索引来扫描行,则可能在执行开始时更新的值在索引中被推送到不同的页面并再次访问同样的执行。如果发生这种情况,该行可能会以不同的结果多次更新。

我的测试没有显示这种行为,但我无法找到是否由SQL Server强制执行,或者我的测试是否正在通过一些偶然的执行计划来阻止它。

可以通过更新到不同的列或使用其他技术来防止这种情况,我只是在问我是否可以信任SQL Server以防止出现这种情况。

3 个答案:

答案 0 :(得分:0)

MS SQL(以及所有主要关系数据库)本质上是事务性的。有时交易是隐含的。但是它可以由BEGIN TRANS,COMMIT和ROLLBACK语句严格控制。 TRANSACTION可以嵌套和分布(跨越单独的数据库和服务器)。 MS SQL运行NASDEQ,所以虽然许多银行家希望它不具有交易安全性,允许它们有效地打印钱,但MS技术人员已经赢得了这一点。对于所有版本的MS SQL,尤其是事务位,基本的MSSQL核心都是相同的。

http://msdn.microsoft.com/en-us/library/ms188929.aspx指的是

简单回答是是

答案 1 :(得分:0)

在这种情况下,您可以信任数据库是完全可预测的。

数据库将使用case表达式的结果更新每条记录,因此每条记录只会更新一次。

它不会分解case表达式,使其成为一个多步更新,它会根据值找到要更新的记录,即它不会将其转换为:

update t
set c1 = 2
where c1 = 1;
update t
set c1 = 3
where c1 = 2

答案 2 :(得分:0)

在后续调查之后,似乎SQL Server对此类行为有所保护。

这个问题众所周知,甚至得到"Halloween Problem"名称。

This post描述了SQL Server解决此问题的方式。

因此,程序员应该能够相信SQL Server会阻止这一点 - 万圣节问题。无需使用附加列或临时表。