事务中非持久计算列的一致性

May*_*erg 1 sql-server

有没有办法防止非持久计算列在事务中更新?

我已经拼凑了一个示例,该示例表明这些列在使用非确定性函数时可以更新(在本例中getutcdate())。这不会破坏事务的一致性要求吗?我曾尝试使用事务级别来防止这种情况(可序列化和快照),但没有帮助。

询问:

set nocount on;

create table dbo.TransactionTest (
    [Timestamp] datetime,
    IsUpdated as case when datediff(second, [Timestamp], getutcdate()) >= 1 then 1 else 0 end
);

insert into dbo.TransactionTest ([Timestamp]) values (getutcdate());

begin tran

select  *
from    dbo.TransactionTest;

waitfor delay '00:00:01';

select  *
from    dbo.TransactionTest;

rollback

drop table dbo.TransactionTest;
Run Code Online (Sandbox Code Playgroud)

结果:

Timestamp               IsUpdated
----------------------- -----------
2017-03-19 00:44:28.130 0

Timestamp               IsUpdated
----------------------- -----------
2017-03-19 00:44:28.130 1
Run Code Online (Sandbox Code Playgroud)

Bre*_*zar 5

这里有几个不同的问题。

问:我可以强制 GETUTCDATE() 在事务期间保持不变吗?

不会。如果您有一个长时间运行的事务,时间会随着您的工作而改变。这与您的隔离级别无关,而与生活没有暂停按钮这一事实有关。(然而。我试过将 Dr. Horrible 的 Freeze Ray 指向我的电脑,但这只会让我的固态硬盘变得更加坚固。)

问:我可以强制非确定性函数每次都返回相同的结果吗?

根据定义,没有。如果可以,它们将是确定性的。

问:如果我需要日期/时间在交易过程中保持不变,我该怎么办?

如果您只需要一个值,请创建一个变量,并在交易开始时设置其值。例如,在 sp_BlitzFirst 中,我设置了一个 @StartSampleTime 变量,然后在整个代码中继续使用它。

如果您需要多行,请将数据选择到像用户表或临时表这样的永久对象中,并在事务的生命周期中反复引用它们。