我在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网站上阅读了有关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-2012版本上运行了上述查询。我已在sql-server-2008下标记了此问题,因为用户在 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)
答案 0 :(得分:2)
isdate所做的就是检查字符串是否可以转换为日期
他们很幸运12是有效的月份
以此为例
SELECT ISDATE('201201'),ISDATE('201301'),ISDATE('199901')
如你所见,1999年也会返回0
当然,你可以玩这样的东西
SELECT ISDATE(CONVERT(DATETIME,0)),ISDATE(CONVERT(DATETIME,''))
答案 1 :(得分:2)
ISDATE将六个字符的字符串解释为yymmdd
。
这取决于配置的cutoff Server Configuration Option。默认值为2049
,因此以< 50
*结尾的年份为20xx
,而>= 50
年为19xx
。
您的测试代码正在处理整数,并在作为参数传递给isdate
且没有前导零时隐式转换为字符串。
答案 2 :(得分:1)
根据您的结果,似乎例如201201
或201301
被解释为YYMMDD
。 (并且第13个月的日期被视为无效。)