我多年来一直使用这种格式来截断日期和时间
SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, '1980-02-05 12:45'), 0) AS Hour ,
DATEADD(DAY, DATEDIFF(DAY, 0, '1980-02-05 12:45'), 0) AS Day ,
DATEADD(MONTH, DATEDIFF(MONTH, 0, '1980-02-05 12:45'), 0) AS Month ,
DATEADD(YEAR, DATEDIFF(YEAR, 0, '1980-02-05 12:45'), 0) AS Year;
但我需要存储像1400-01-01
这样的早期日期,因此我可以使用DateTime2
。
但是,如何才能支持使用DateTime2
仍然截断上述内容的功能?
将上面的年份从1400
更改为1980
将导致
SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, '1400-02-05 12:45'), 0) AS Hour ,
DATEADD(DAY, DATEDIFF(DAY, 0, '1400-02-05 12:45'), 0) AS Day ,
DATEADD(MONTH, DATEDIFF(MONTH, 0, '1400-02-05 12:45'), 0) AS Month ,
DATEADD(YEAR, DATEDIFF(YEAR, 0, '1400-02-05 12:45'), 0) AS Year;
导致将varchar数据类型转换为日期时间数据类型 在超出范围的价值。
投射到DateTime2
SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, CAST('1400-02-05 12:45' AS DATETIME2)),0) AS Hour ,
DATEADD(DAY, DATEDIFF(DAY, 0, CAST('1400-02-05 12:45' AS DATETIME2)),0) AS Day ,
DATEADD(MONTH, DATEDIFF(MONTH, 0, CAST('1400-02-05 12:45' AS DATETIME2)), 0) AS Month ,
DATEADD(YEAR, DATEDIFF(YEAR, 0, CAST('1400-02-05 12:45' AS DATETIME2)), 0) AS Year;
将datetime2数据类型转换为日期时间数据类型 导致了超出范围的价值。
我假设0
被视为DateTime
数据类型并有效地将其投放到DateTime
。
尝试使用0
将DateTime2
转换为CAST(0 AS DATETIME2)
会给我这个错误
不允许从数据类型int到datetime2的显式转换。
最后,我想在表中使用这些作为持久列,这些列与DateTime
数据类型配合得很好,但DateTime2
答案 0 :(得分:2)
您应该使用某个特定的基准日期而不是0
。 0
可以隐式转换为datetime
类型。对于datetime2
,不允许进行此类隐式转换。此外,基准日期应为datetime2
类型。然后DATEDIFF
和DATEADD
将使用datetime2
值。
使用显式基准日期的另一个原因是您需要将此基准日期作为一年中的第一天,并且00:00:00
时间使公式正常工作。隐含的开始日期,例如转换为0
的{{1}}或转换为datetime
的{{1}}现在也具有这些属性,但您是否真的想依赖该类型的内部细节实施?最好明确说明这些事情,这样可以让新人更易于理解。
此外,如果您想要使用相同的方法截断到星期边界,那么您必须选择星期一的基准日期(如果您的星期一是星期一开始)或星期日(如果您的星期日开始于星期日) )。公式保持不变,但基准日期很重要。
示例1 - 工作
''
示例2 - 工作
datetime2
示例3 - 无效
DECLARE @VarBase datetime2 = '2000-01-01';
DECLARE @VarValue datetime2 = '1400-02-05 12:45';
SELECT
DATEADD(HOUR, DATEDIFF(HOUR, @VarBase, @VarValue), @VarBase) AS Hour,
DATEADD(DAY, DATEDIFF(DAY, @VarBase, @VarValue), @VarBase) AS Day,
DATEADD(MONTH, DATEDIFF(MONTH, @VarBase, @VarValue), @VarBase) AS Month,
DATEADD(YEAR, DATEDIFF(YEAR, @VarBase, @VarValue), @VarBase) AS Year;
向'datetime'列添加值会导致溢出。
它不起作用,因为文字SELECT
DATEADD(HOUR, DATEDIFF(HOUR, @VarBase, '1400-02-05 12:45'), @VarBase) AS Hour,
DATEADD(DAY, DATEDIFF(DAY, @VarBase, '1400-02-05 12:45'), @VarBase) AS Day,
DATEADD(MONTH, DATEDIFF(MONTH, @VarBase, '1400-02-05 12:45'), @VarBase) AS Month,
DATEADD(YEAR, DATEDIFF(YEAR, @VarBase, '1400-02-05 12:45'), @VarBase) AS Year;
转换为SELECT
DATEADD(HOUR, DATEDIFF(HOUR, '2000-01-01', '1400-02-05 12:45'), '2000-01-01') AS Hour,
DATEADD(DAY, DATEDIFF(DAY, '2000-01-01', '1400-02-05 12:45'), '2000-01-01') AS Day,
DATEADD(MONTH, DATEDIFF(MONTH, '2000-01-01', '1400-02-05 12:45'), '2000-01-01') AS Month,
DATEADD(YEAR, DATEDIFF(YEAR, '2000-01-01', '1400-02-05 12:45'), '2000-01-01') AS Year;
,而不是2000-01-01
。
示例4 - 作品
datetime
答案 1 :(得分:1)
尝试使用:
DECLARE @Default DATETIME2 = CAST('' AS DATETIME2)
SELECT DATEADD(HOUR, DATEDIFF(HOUR, @Default, CAST('1400-02-05 12:45' AS DATETIME2)), @Default) AS Hour ,
DATEADD(DAY, DATEDIFF(DAY, @Default, CAST('1400-02-05 12:45' AS DATETIME2)), @Default) AS Day ,
DATEADD(MONTH, DATEDIFF(MONTH, @Default, CAST('1400-02-05 12:45' AS DATETIME2)), @Default) AS Month ,
DATEADD(YEAR, DATEDIFF(YEAR, @Default, CAST('1400-02-05 12:45' AS DATETIME2)), @Default) AS Year;
答案 2 :(得分:1)
我发现如果我使用转换而不是使用CAST('DateTimeData'作为DateTime2),它可以是确定性的结果。
如本帖所述:Cannot persist computed column - not deterministic
ALTER TABLE dbo.QuakeRawJSON
ADD [Date] AS (DATEADD(DAY,DATEDIFF(DAY, CONVERT(DATETIME2,'',112)
,origintime),CONVERT(DATETIME2,'',112))) PERSISTED;
感谢您的帮助。