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

时间:2012-08-20 08:53:52

标签: sql-server concurrency getdate

假设

isnull(some_column, getdate()) >= getdate()

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

5 个答案:

答案 0 :(得分:5)

不,不安全。您正面临所谓的runtime constants表达式,其中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

就我而言,这是立刻被击中的:

Msg 50000, Level 16, State 1, Line 9
@cnt = 2515 this shoudl not happen but it dit after @i = 694

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

语料中的

GETDATE()两次将进行两次评估

答案 1 :(得分:3)

由于您在条件中寻找真实,因此您无需使用getDate()两次。只是放入一个非常大的日期......

例如:

isnull(some_column, '2999-01-01') >= getDate()

,如

declare @some_column(datetime)
select case when isnull(@some_column,'2999-01-01') >= getdate() then 1 else 0 end

返回1.

或者,您可以正确执行此操作并明确检查null:

(some_column >= getdate() or some_column is null)

答案 2 :(得分:2)

由于 两次调用GETDATE(),此可能失败,但大部分时间它都可以正常工作。

您可以执行以下操作来缓解:

DECLARE currentDate DATETIME

SELECT currentDate = GETDATE()

isnull(some_column, currentDate) >= currentDate 

答案 3 :(得分:1)

在SQL Server 2000和以前的版本中,getdate()是一个按每个SQL语句评估ONCE的确定性函数。从2005年开始,getdate不是确定性的,每次都会对它进行评估,因此您应该将值赋给变量。

答案 4 :(得分:0)

为什么要使用日期?我的意思是没有理由要求sql server评估/处理默认的真实条件。 您可以改为使用

isnull(some_column, 2) >= 1