有没有办法防止非持久计算列在事务中更新?
我拼凑了一个示例,该示例表明这些列在使用非确定性函数时可以更新(在本例中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;
结果:
Timestamp IsUpdated
----------------------- -----------
2017-03-19 00:44:28.130 0
Timestamp IsUpdated
----------------------- -----------
2017-03-19 00:44:28.130 1
这里有几个不同的问题。
问:我可以强制 GETUTCDATE() 在交易期间保持不变吗?
不会。如果您有一个长时间运行的事务,则时间会在您工作时发生变化。这与你的隔离级别无关,更多的是因为生活没有暂停键。(然而。我曾尝试将 Dr. Horrible 的 Freeze Ray 对准我的电脑,但这只会让我的固态硬盘变得更加坚固。)
问:我可以强制非确定性函数每次都返回相同的结果吗?
根据定义,没有。如果可以的话,它们将是确定性的。
问:如果我需要日期/时间在交易期间保持不变,我该怎么办?
如果您只需要一个值,请创建一个变量,并在事务开始时设置它的值。例如,在 sp_BlitzFirst 中,我设置了一个 @StartSampleTime 变量,然后在整个代码中继续使用它。
如果您需要多行,请将数据选择到永久对象(如用户表或临时表)中,并在事务生命周期中重复引用它们。