Mar*_*ith 55 sql-server datatypes date time datetime2
鉴于以下组件
DECLARE @D DATE = '2013-10-13'
DECLARE @T TIME(7) = '23:59:59.9999999'
Run Code Online (Sandbox Code Playgroud)
将它们结合起来以产生DATETIME2(7)具有价值的结果的最佳方法是'2013-10-13 23:59:59.9999999'什么?
有些东西不工作,如下表所示。
SELECT @D + @T
Run Code Online (Sandbox Code Playgroud)
操作数数据类型日期对加法运算符无效。
SELECT CAST(@D AS DATETIME2(7)) + @T
Run Code Online (Sandbox Code Playgroud)
操作数数据类型 datetime2 对加法运算符无效。
SELECT DATEADD(NANOSECOND,DATEDIFF(NANOSECOND,CAST('00:00:00.0000000' AS TIME),@T),@D)
Run Code Online (Sandbox Code Playgroud)
datediff 函数导致溢出。分隔两个日期/时间实例的日期部分数量太大。尝试将 datediff 与不太精确的日期部分一起使用。
* 可以在 Azure SQL 数据库和 SQL Server 2016 中避免溢出,使用DATEDIFF_BIG.
SELECT CAST(@D AS DATETIME) + @T
Run Code Online (Sandbox Code Playgroud)
数据类型 datetime 和 time 在 add 运算符中不兼容。
SELECT CAST(@D AS DATETIME) + CAST(@T AS DATETIME)
Run Code Online (Sandbox Code Playgroud)
返回结果但失去精度
2013-10-13 23:59:59.997
ype*_*eᵀᴹ 54
这似乎有效并保持精度:
SELECT DATEADD(day, DATEDIFF(day,'19000101',@D), CAST(@T AS DATETIME2(7)))
Run Code Online (Sandbox Code Playgroud)
在CAST以DATETIME2(7)转换TIME(7)价值(@T)到DATETIME2其中的日期部分'1900-01-01',这是迄今为止的默认值和时间类型(见datetime2和注释*在CAST和CONVERT页面在MSDN。)
* ... 当仅表示日期或仅表示时间分量的字符数据转换为 datetime 或 smalldatetime 数据类型时,未指定的时间分量设置为 00:00:00.000,未指定的日期分量设置为 1900-01- 01 .
该DATEADD()和DATEDIFF()功能照料休息,即在天之间将差异1900-01-01和DATE价值(@D)。
测试:SQL-Fiddle
正如@Quandary所注意到的,SQL Server 认为上述表达式是不确定的。如果我们想要一个确定性表达式,比如因为它用于PERSISTED列,则'19000101'**需要替换为0or 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
) ;
Run Code Online (Sandbox Code Playgroud)
**:DATEDIFF(day, '19000101', d)不是确定性的,因为它隐式地将字符串DATETIME转换为日期时间,并且只有在使用特定样式时才具有确定性。
knu*_*les 13
我迟到了,但是这种方法虽然类似于@ypercube 的答案,但避免了使用任何字符串转换(这可能比日期转换更昂贵)的需要,是确定性的,如果 MS 更改了1900-01-01 的默认日期值(即使他们可能不会改变这一点):
DECLARE @D DATE = SYSUTCDATETIME()
, @T TIME = SYSUTCDATETIME();
SELECT DATEADD(DAY, DATEDIFF(DAY, @T, @D), CONVERT(DATETIME2, @T));
Run Code Online (Sandbox Code Playgroud)
原理是通过将时间值转换为 datetime2 然后转换为日期,它去除超时并分配默认日期,然后将日期与您的日期值进行比较以获得要添加的天数,将您的时间转换为 datetime2 并添加天。
对于 SQL Server 2012 及更高版本,有DATETIME2FROMPARTS函数。它有这样的形式:
DATETIME2FROMPARTS(year, month, day, hour, minute, seconds, fractions, precision)
Run Code Online (Sandbox Code Playgroud)
对于给定的样本数据,这变为
select Answer = DATETIME2FROMPARTS(2013, 10, 13, 23, 59, 59, 9999999, 7);
Run Code Online (Sandbox Code Playgroud)
这导致
Answer
---------------------------
2013-10-13 23:59:59.9999999
Run Code Online (Sandbox Code Playgroud)
如果从时间数据类型开始,或从用于构建问题中的样本值的文本开始,则可以使用DATEPART()获得这些部分。