将 0 转换为 DATE 和 DATETIME
Posted
技术标签:
【中文标题】将 0 转换为 DATE 和 DATETIME【英文标题】:Casting 0 as DATE and DATETIME 【发布时间】:2017-01-13 21:08:26 【问题描述】:我只是偶然发现了这个,找不到任何技术解释:
在 SQL Server 2014 中:
SELECT CAST('' AS DATETIME);
1900-01-01 00:00:00.000
SELECT CAST(0 AS DATETIME);
1900-01-01 00:00:00.000
SELECT CAST('' AS DATE);
1900-01-01
SELECT CAST(CAST(0 AS DATETIME) AS DATE);
1900-01-01
SELECT CAST(0 AS DATE);
消息 529,第 16 级,状态 2,第 4 行 不允许从数据类型 int 到 date 的显式转换。
为什么从空字符串到DATE
和DATETIME
的CAST
可以工作,而从0
它只能作为DATETIME
工作?
我对技术解释感兴趣
【问题讨论】:
msdn.microsoft.com/en-us/library/ms191530.aspx 【参考方案1】:我认为这是微软选择支持什么的问题。或多或少归结为这样一个事实,即允许从数值转换为日期时间,而日期不允许从数值转换。在 SQL Server 中,它必须首先将 0 转换为数值,例如 0.000000000,然后再转换为该数字的等效日期时间。我的示例显示可以将当前日期转换为数值,然后再转换回日期时间。但是,转换为日期会引发错误。如果您尝试将值 0.5 转换为日期,我想避免可能遇到的舍入问题。在这种情况下,将编程 SQL 引擎以将 0.5 隐式转换为日期 1900-01-01 或 1900-01-02。在这种情况下,您必须就应返回的日期做出任意决定。
这行得通:
--produces a numeric value like 42746.97660799
select cast(getdate() as numeric(18,8))
select cast(42746.97660799 as datetime)
虽然这会引发您收到的相同错误:
select cast(42746.97660799 as date)
消息 529,第 16 级,状态 2,第 5 行 不允许将数据类型从数字显式转换为日期。
【讨论】:
好点,我没有这么想。如果您可以将 int 转换为日期,并且可以将数字转换为 int,那么您可以将数字(非 int)转换为日期,创建任意轮次。很好的答案!【参考方案2】:您的第一个问题,为什么不能将 0 转换为 Date,这是从 Int 到 Date 的非法转换(请参阅链接文档中的矩阵)
我在找到类似代码后发现了您的问题,并想知道为什么 cast(0 as datetime) 会产生 1900-01-01。我想知道这是一个我可以信任的“标准”还是未定义的“在我们改变它之前它会一直这样工作”。我什至发现了其他建议 Epoch 是 1900 的 SO 帖子,但找不到任何官方文档。
在阅读 Cast/Convert 文档时,可以参考 Cast 将在缺少 Year 或 Time 时执行的操作(尽管在 varchar 转换部分)。未定义时,日期默认为 1900-01-01,时间默认为 00:00:00。 (参见链接文档中的下标 6)。文章中有示例代码将时间转换为日期时间,并为日期部分生成 1900-01-01。
这(谢天谢地?!)产生 0(而 1753 的最小日期产生一个很大的负数)
select cast(cast('1900-01-01' as datetime) as Int)
标题为“CAST and CONVERT (Transact-SQL)”的 Microsoft 文档
https://docs.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver15
【讨论】:
【参考方案3】:这可能来自时间戳行为。 您可以将 0 转换为日期时间,然后转换为日期。 这也是微软的规则。不是国家规定。
【讨论】:
发帖者:我对技术解释很感兴趣 您添加了一条重要信息,将 0 转换为 DATETIME,然后转换为 DATE 工作。我将把它添加到问题中。【参考方案4】:除了 SQL Server 支持的内容之外,我不确定是否有很多干净的技术解释。 SQL Server 对其所有数据类型进行排名Data Type Precendence。隐式转换随着时间的推移而演变。 Craig Friedman 的 Microsoft 博客很好地解释了逻辑和演变More on Implicit Conversions。 @hamid_reza hobab 所指出的基本上是正确的。 SQL Server 支持将 int 转换为日期时间。日期时间的优先级高于日期,因此可以将日期时间转换为日期。 SQL Server 不支持将 int 隐式或显式转换为 date,如 @dfundako 在评论中发布的支持矩阵中所示
【讨论】:
以上是关于将 0 转换为 DATE 和 DATETIME的主要内容,如果未能解决你的问题,请参考以下文章