给定以下组件
DECLARE @D DATE = '2013-10-13' DECLARE @T TIME(7) = '23:59:59.9999999'
将它们结合起来以产生DATETIME2(7)具有价值的结果的最佳方法是什么'2013-10-13 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.
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
2013-10-13 23:59:59.997
这似乎工作并保持精度:
SELECT DATEADD(day, DATEDIFF(day,'19000101',@D), CAST(@T AS DATETIME2(7)))
CASTto将值 ( )DATETIME2(7)转换为 date 部分所在的a ,这是 date 和 datetime 类型的默认值(请参阅MSDN上的注释*和页面。)TIME(7)``@T``DATETIME2``'1900-01-01'datetime2CAST``CONVERT
CAST
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。
DATEADD()
DATEDIFF()
1900-01-01
DATE
@D
测试:SQL-Fiddle
正如所注意到的,上述表达式被 SQL Server 认为是不确定的。如果我们想要一个确定性表达式,比如说因为它要用于PERSISTED列,则'19000101'**需要替换为0or CONVERT(DATE, '19000101', 112):
PERSISTED
'19000101'
0
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 ) ;