SQL Server中的IsDate函数是将201301视为YYYYMM还是YYMMDD?

时间:2013-02-14 21:24:09

标签: sql-server sql-server-2008 sql-server-2012

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

我在Microsoft Connection网站上看到了以下错误报告。用户报告IsDate (Transact-SQL)函数正在验证 YYYYMM 格式的句点,涉及 2012 但是从 2013开始就停止了工作

ISDate() returns different results beginning in 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月期间数据的快照。值200229被IsDate认为有效,但不是200230,这使我认为IsDate将格式 YYMMDD 的值视为用户期待的YYYYMM

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

问题:

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

  • 如果 YYMMDD 确实是该功能正在尝试评估的格式,那么它代表的是哪个世纪。它是否代表年份 1920 2020 或其他内容的值?或者没关系?

  • 我将上述查询中的起始值和结束值替换为下面提到的值。我还列出了在这些范围之间找到的有效行数。为什么 00 09 的年终不会返回任何行?

多次尝试:

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)

3 个答案:

答案 0 :(得分:2)

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

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

以此为例

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

如你所见,1999年也会返回0

当然,你可以玩这样的东西

SELECT ISDATE(CONVERT(DATETIME,0)),ISDATE(CONVERT(DATETIME,''))

答案 1 :(得分:2)

  1. ISDATE将六个字符的字符串解释为yymmdd

  2. 这取决于配置的cutoff Server Configuration Option。默认值为2049,因此以< 50 *结尾的年份为20xx,而>= 50年为19xx

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

答案 2 :(得分:1)

根据您的结果,似乎例如201201201301被解释为YYMMDD。 (并且第13个月的日期被视为无效。)