6

认为

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

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

4

5 回答 5

7

不,不安全。您面临所谓的运行时常量表达式,其中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()语句中的两次将被评估两次

于 2012-08-20T08:59:12.343 回答
3

由于您在条件中寻找 true,因此您不需要使用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)
于 2012-08-20T08:59:09.230 回答
3

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

于 2012-08-20T09:11:16.300 回答
2

由于您调用GETDATE()两次,这可能会失败,但大多数情况下它会正常工作。

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

DECLARE currentDate DATETIME

SELECT currentDate = GETDATE()

isnull(some_column, currentDate) >= currentDate 
于 2012-08-20T08:57:28.170 回答
0

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

isnull(some_column, 2) >= 1
于 2012-08-20T11:01:15.130 回答