假设
isnull(some_column, getdate()) >= getdate()
其中的逻辑是,如果some_column为null,该表达式应该永远是正确的。 然而这将永远是这样(因为GETDATE的两次评价()之间有一段时间已经过去了,他们是不相等的)?
假设
isnull(some_column, getdate()) >= getdate()
其中的逻辑是,如果some_column为null,该表达式应该永远是正确的。 然而这将永远是这样(因为GETDATE的两次评价()之间有一段时间已经过去了,他们是不相等的)?
没有,是不是安全的。 你正面临所谓的运行时间常量表达式,其中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()
在一份声明中两次将两次评估
既然你是在条件寻找真正的,你不需要使用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。
另外,您可以正确做到这一点,检查空明确:
(some_column >= getdate() or some_column is null)
既然你是调用GETDATE()
两次,这可能会失败,但大多数时间它会工作的权利。
你可以做到以下几点,以减轻:
DECLARE currentDate DATETIME
SELECT currentDate = GETDATE()
isnull(some_column, currentDate) >= currentDate
在SQL Server 2000和以前的版本,GETDATE()为每个SQL语句评估一次一个确定性的函数。 从2005年和上GETDATE不确定性,每一次它的评估,所以你应该赋值给变量。
你为什么要使用日期。 我的意思是有没有理由要求SQL Server来评估/进程的一个默认的真实情况。 您可以改用
isnull(some_column, 2) >= 1