5

有人在 Microsoft Connect 上报告了此错误:

我在 Microsoft Connection 网站上遇到了以下错误报告。用户报告该功能正在验证涉及2012 年IsDate (Transact-SQL)期间的格式的期间,但自2013年初以来停止工作。YYYYMM

ISDate() 从 2013 年开始返回不同的结果

用户报告以下作为输入数据。我已经列出了用户的期望和 SQL Server 的输出。

SELECT  ISDATE(201201)      AS CheckDate1   --Expected: 1; Actual: 1
    ,   ISDATE(201301)      AS CheckDate2   --Expected: 1; Actual: 0
    ,   ISDATE(201401)      AS CheckDate3   --Expected: 1; Actual: 0
    ,   ISDATE(20130101)    AS CheckDate4   --Expected: 1; Actual: 1

阅读 MSDN 文档:

我在 MSDN 网站上阅读了有关ISDATE (Transact-SQL). 该文档说明了以下定义,但找不到任何可以YYYYMM验证该函数正在验证的示例。

Returns 1 if the expression is a valid date, time, or datetime value; 
otherwise, 0.

在关于数据类型datetime (Transact-SQL)的定义中,我找不到任何暗示YYYYMM是有效日期格式的东西。用户指定的值也不是datetime2格式。

我编写了以下脚本以了解发生了什么。

查询试图找出发生了什么:

DECLARE @StartAt    INT;
DECLARE @EndAt      INT;

SET @StartAt    = 200000;
SET @EndAt      = 201312;

;WITH Numbers AS 
(
    SELECT @StartAt AS n
    UNION ALL
    SELECT n + 1 FROM Numbers WHERE n < @EndAt
)
SELECT  n           AS Number
    ,   ISDATE(n)   AS IsValidDate 
FROM    Numbers 
WHERE   ISDATE(n) <> 0
OPTION (MAXRECURSION 10000);

以上查询结果:

上述查询在2012 年的每一天返回366行。这是 2 月至 3 月之间数据的快照。IsDate 认为值 200229 是有效的,但不是 200230,这让我认为 IsDate 正在处理这些格式值,而不是像用户期望的那样。YYMMDDYYYYMM

Number  IsValidDate
------  -----------
200227        1
200228        1
200229        1
200301        1
200302        1
200303        1

问题:

  • 我是否正确IsDate将上述值视为YYMMDD而不是YYYYMM

  • 如果YYMMDD确实是函数试图评估的格式,它代表哪个世纪。它是否代表年份19202020其他值?还是没关系?

  • 我用下面提到的那些替换了上述查询中的开始和结束值。我还列出了在这些范围之间找到的有效行数。为什么以0009结尾的年份不返回任何行?

多次尝试:

Start   End     Rows
------  ------  ----
000000  001231     0
010000  011231     0
020000  021231     0
030000  031231     0
040000  041231     0
050000  051231     0
060000  061231     0
070000  071231     0
080000  081231     0
090000  091231     0
100000  101231   365
110000  111231   365
120000  121231   366
...
...
980000  981231   365
990000  991231   365

我用来运行上述查询的 SQL Server 版本:

版本上运行了上述查询。我在Microsoft Connect网站上的那个版本下报告了这个问题。

Microsoft SQL Server 2012 - 11.0.2316.0 (X64) 
Apr  6 2012 03:20:55 
Copyright (c) Microsoft Corporation
Enterprise Edition (64-bit) on Windows NT 6.1 <X64> 
(Build 7601: Service Pack 1) (Hypervisor)
4

3 回答 3

2

isdate 所做的只是检查字符串是否可以转换为日期

他们很幸运 12 是一个有效的月份

以此为例

SELECT ISDATE('201201'),ISDATE('201301'),ISDATE('199901')

如您所见, 1999 也返回 0

当然,您可以享受这样的乐趣

SELECT ISDATE(CONVERT(DATETIME,0)),ISDATE(CONVERT(DATETIME,''))
于 2013-02-14T21:34:41.217 回答
2
  1. ISDATE将六个字符的字符串解释为yymmdd.

  2. 它取决于配置的截止服务器配置选项。默认是2049,所以以< 50* 结尾的年份是20xx,年份>= 5019xx

  3. 您的测试代码正在处理整数,并且在作为参数传递给isdate没有前导零时隐式转换为字符串。

于 2013-02-14T21:56:26.187 回答
1

根据您的结果,例如201201或被201301解释为YYMMDD。(然后认为第 13 个月的日期无效。)

于 2013-02-14T21:35:36.220 回答