给定以下组件
DECLARE @D DATE = '2013-10-13'
DECLARE @T TIME(7) = '23:59:59.9999999'
将它们结合起来以产生DATETIME2(7)
具有价值的结果的最佳方法是什么'2013-10-13 23:59:59.9999999'
?
下面列出了一些不起作用的东西。
SELECT @D + @T
操作数数据类型日期对于加法运算符无效。
SELECT CAST(@D AS DATETIME2(7)) + @T
操作数数据类型 datetime2 对 add 运算符无效。
SELECT DATEADD(NANOSECOND,DATEDIFF(NANOSECOND,CAST('00:00:00.0000000' AS TIME),@T),@D)
datediff 函数导致溢出。分隔两个日期/时间实例的日期部分的数量太大。尝试将 datediff 与不太精确的日期部分一起使用。
* 在 Azure SQL 数据库和 SQL Server 2016 中,使用DATEDIFF_BIG
.
SELECT CAST(@D AS DATETIME) + @T
数据类型 datetime 和 time 在 add 运算符中不兼容。
SELECT CAST(@D AS DATETIME) + CAST(@T AS DATETIME)
返回结果但丢失精度
2013-10-13 23:59:59.997
这似乎工作并保持精度:
SELECT DATEADD(day, DATEDIFF(day,'19000101',@D), CAST(@T AS DATETIME2(7)))
CAST
to将值 ( )DATETIME2(7)
转换为 date 部分所在的a ,这是 date 和 datetime 类型的默认值(请参阅MSDN上的注释*和页面。)TIME(7)``@T``DATETIME2``'1900-01-01'
datetime2
CAST``CONVERT
* … 当仅表示日期或仅表示时间分量的字符数据转换为 datetime 或 smalldatetime 数据类型时,未指定的时间分量设置为 00:00:00.000,未指定的日期分量设置为 1900-01- 01 .
DATEADD()
andDATEDIFF()
函数负责其余部分,即添加 和 值 ( ) 之间的天1900-01-01
数DATE
差@D
。
测试:SQL-Fiddle
正如所注意到的,上述表达式被 SQL Server 认为是不确定的。如果我们想要一个确定性表达式,比如说因为它要用于PERSISTED
列,则'19000101'
**需要替换为0
or CONVERT(DATE, '19000101', 112)
:
CREATE TABLE date_time
( d DATE NOT NULL,
t TIME(7) NOT NULL,
dt AS DATEADD(day,
DATEDIFF(day, CONVERT(DATE, '19000101', 112), d),
CAST(t AS DATETIME2(7))
) PERSISTED
) ;