首页 > 解决方案 > 为什么 ISDATE(YEAR(GETDATE())) 返回 1?

问题描述

为什么ISDATE(YEAR(GETDATE()))orISDATE(2020)ISDATE(<any four digit number>)or会ISDATE(<any expression that returns a four digit number>)返回 1?

所有这些都返回 1,我们真的可以依靠 ISDATE()来知道表达式是否是日期表达式吗?

这就是我担心的原因:
SELECT ISDATE(4000-2000)返回 1 尽管它不是日期表达式。

标签: sql-serverdate

解决方案


因为ISDATE(like ISNUEMRIC) 不是一个很好的功能。ISDATE设计时考虑了较旧的日期和时间数据类型 ( datetimeand smalldatetime),这意味着 aint可以隐式转换为日期和时间。这不适用于新的 Date 和 Time 数据类型(例如datetime2and date)。

对于较旧的数据类型,一个int值表示1900-01-01. 如此0,将来也会1900-01-01如此。因此将是。21900-01-0320201905-07-14

如果您确实想查看某个值是否是有效的日期和时间值,对于您使用的数据类型,请使用TRY_CONVERT. 例如TRY_CONVERT(date,2020)将返回NULL,因为2020无法转换。另一方面TRY_CONVERT(datetime,2020)将返回1905-07-14,因为它可以转换;即使该值不是您所期望的。

附加说明:4 位字符串也可以隐式转换。一个 4 位字符串将仅表示日期的年份,因此'2000'将表示2000-01-01. 对于较旧的日期和时间数据类型以及新的数据类型都是如此。两者都TRY_CONVERT(date,'2020')TRY_CONVERT(datetime,'2020')返回2020-01-01

正如 Martin Smith 所提到的,上面的注释实际上与这里发生的事情更相关。根据ISDATE (Transact-SQL)的参数为ISDATE

是可以转换为字符串的字符串或表达式。表达式必须少于 4,000 个字符。日期和时间数据类型,除了 datetime 和 smalldatetime,不允许作为 ISDATE 的参数。

这意味着表达式ISDATE(2020)ISDATE('2020')是同义词。这实际上非常糟糕,因为2020 不能(隐式或显式)转换为 a date,但可以转换为datetime. 这进一步(在我看来)巩固了ISDATE应该避免的情况。考虑到它TRY_CONVERT在所有受支持的 SQL Server 版本(包括扩展支持的版本)中都可用,这是迄今为止更安全的选择。


推荐阅读