0

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 来防止这种情况。

4

3 回答 3

0

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

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

它不会分解case表达式以使其成为多步更新,它会根据值查找要更新的记录,即它不会将其变成:

update t
set c1 = 2
where c1 = 1;
update t
set c1 = 3
where c1 = 2
于 2013-06-24T15:43:48.040 回答
0

经过进一步调查,似乎 SQL Server 对这种行为有保护作用。

这个问题是众所周知的,甚至得到了“万圣节问题”的名称。

这篇文章描述了 SQL Server 解决这个问题的方式。

因此,程序员应该能够相信 SQL Server 会阻止这种情况——万圣节问题。无需额外的列或临时表。

于 2013-06-24T18:20:19.947 回答
0

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

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

简单的答案是肯定的

于 2013-06-24T15:39:35.920 回答