在一个语句中两次评估GETDATE - 它总是评估为相同吗?

ren*_*ren 6 sql-server concurrency getdate

假设

isnull(some_column, getdate()) >= getdate()
Run Code Online (Sandbox Code Playgroud)

其中逻辑是,如果some_column为null,则此表达式应始终为true.然而,这总是如此(因为在两次getdate()评估之间已经过了一段时间并且它们不会相等)?

Rem*_*anu 6

不,不安全.您正面临所谓的运行时常量表达式,其中的GETDATE()是书架示例,它在查询启动时计算一次,然后使用缓存的计算值.但是,每次出现都要单独评估一次,并且两次评估可以落在日期时间精度边界的不同侧,从而产生两个不同的值.

一个简单的测试揭示了这种情况:

declare @cnt int = 0, @i int = 0
while @cnt = 0 
begin
    select @cnt = count(*)
    from master..spt_values 
    where getdate() != getdate();
    set @i += 1;
    if @cnt != 0
        raiserror(N'@cnt = %d this shoudl not happen but it dit after @i = %d', 16, 1, @cnt, @i);
end
Run Code Online (Sandbox Code Playgroud)

在我的情况下,这是立即被击中:

Msg 50000, Level 16, State 1, Line 9
@cnt = 2515 this shoudl not happen but it dit after @i = 694
Run Code Online (Sandbox Code Playgroud)

我没有解决如何更好地做到这一点的问题(你已经有了很多建议),但是关于运行时执行的假设是否正确(不是)的基本问题:

GETDATE() 两次声明将被评估两次