2016-09-06 93 views
0

我有如下表:SQL Server | IsNull | datetime和smalldatetime

create table #temp_1234 
(
    field1 varchar(50) null, 
    field2 datetime null, 
    field3 smalldatetime null 
) 

,并说,我插入下面的一行到它:

insert into #temp_1234 
(field1, field2, field3) 
values ('Val1','2016-09-16 23:59:59.000',NULL) 

如果我执行查询

select field2 from #temp_1234 

我得到的结果是'2016-0 9-16 23:59:59.000'。


但是,当我执行查询

select ISNULL(field3,field2) from #temp_1234 

结果变成了是 '2016年9月17日零时00分00秒'。


这是如何,即使在两个查询中同一列被返回,结果在两种情况下是不同的?

据我所知,“SMALLDATETIME”是精确高达一分钟,和“日期时间”是精确高达一秒钟。但是如何引入空检查会改变返回结果的精度?

+0

isnull强制第一个输入的数据类型(或者说,将第二个输入转换为第一个)。例如'DECLARE @ var1 VARCHAR(5); DECLARE @ var2 VARCHAR(10)='asdfghjkl;'; SELECT ISNULL(@ var1,@ var2);'会产生'asdfg'...所以你迫使field2成为isnull中的一个小日期时间。 – ZLK

回答

3

ISNULL利用两个参数,check_expressionreplacement_value。如文档中所述,replacement_value

如果check_expression为NULL,则返回表达式。 replacement_value必须是可隐式转换为check_expresssion类型的类型。

实质上,SQL查询引擎会隐式转换值以进行比较。 Datetime的准确率为3.33ms,所以最有可能占四舍五入。

如果您想获得对转换的更多控制权,请考虑使用explicit conversions,如CASTCONVERT

这可能也是COALESCE函数的一个很好的用例,而不是ISNULL

0

isnull将第二个值转换为第一个值格式。

这是更清楚:

DECLARE @date日期,日期时间@datetime = GETDATE() 选择ISNULL(@date,@datetime)

0
select ISNULL(field3,field2) from #temp_1234 

当exceute上述查询,值因为field3的数据类型是smalldatetime,所以将“field2”的类型转换为类型smalldatetime。这就是为什么ISNULL会返回不同的值。要验证您可以运行下面的查询:

select cast(field2 as smalldatetime) from #temp_1234 

smalldatetime秒节始终为零(00)。如果datetime的值具有大于或等于30的秒数,则将1分钟添加到产生的smalldatetime值并将秒设置为零。对于少于30秒的结果,smalldatetime值的秒部分设置为00并且分钟部分与之前相同。

您的情况datetime的值为:'2016-09-16 23:59:59.000'。由于日期时间值的秒段大于30,因此1分钟会添加到生成的smalldatetime值中,该值会给出值'2016-09-17 00:00:00'。