【问题标题】:Casting 0 as DATE and DATETIME将 0 转换为 DATE 和 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 的显式转换。

为什么从空字符串到DATEDATETIMECAST 可以工作,而从0 它只能作为DATETIME 工作?

我对技术解释感兴趣

【问题讨论】:

标签: sql sql-server casting sql-server-2014


【解决方案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 在评论中发布的支持矩阵中所示

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-12
      • 1970-01-01
      相关资源
      最近更新 更多