这可能取决于多种因素 - 操作系统的区域设置、当前用户的语言和日期格式设置。默认情况下,Windows 使用US English
,用户的设置是US English
和MDY
。
但这里有一些例子来说明这种情况如何改变。
用户正在使用英国语言设置:
-- works:
SET LANGUAGE BRITISH;
SELECT CONVERT(DATETIME, '30-04-2012 19:01:45');
-- fails:
SELECT CONVERT(DATETIME, '04/13/2012');
GO
(错误)
消息 242,级别 16,状态 3,第 5 行
将 varchar 数据类型转换为 datetime 数据类型导致值超出范围。
用户正在使用法语:
-- works:
SET LANGUAGE FRENCH;
SELECT CONVERT(DATETIME, '30-04-2012 19:01:45');
-- fails:
SELECT CONVERT(DATETIME, '04/13/2012');
GO
(错误)
Msg 242, Level 16, State 3, Line 1
La conversion d'un type de données varchar en type de données datetime a créé une valeur hors limites。
用户再次使用 Français:
SET LANGUAGE FRENCH;
-- fails (proving that, contrary to popular belief, YYYY-MM-DD is not always safe):
SELECT CONVERT(DATETIME, '2012-04-30');
GO
(错误)
Msg 242, Level 16, State 3, Line 1
La conversion d'un type de données varchar en type de données datetime a créé une valeur hors limites。
用户使用 DMY 而不是 MDY:
SET LANGUAGE ENGLISH;
SET DATEFORMAT DMY;
-- works:
SELECT CONVERT(DATETIME, '30-04-2012 19:01:45');
-- fails:
SELECT CONVERT(DATETIME, '04-30-2012');
GO
(错误)
消息 242,级别 16,状态 3,第 2 行
将 varchar 数据类型转换为 datetime 数据类型导致值超出范围。
您最好的选择始终是使用 ISO 标准、非区域、安全、明确的日期格式。我通常推荐的两个是:
YYYYMMDD - for date only.
YYYY-MM-DDTHH:MM:SS[.mmm] - for date + time, and yes that T is important.
这些都没有失败:
SET DATEFORMAT MDY;
SET LANGUAGE ENGLISH;
SELECT CONVERT(DATETIME, '20120430');
SELECT CONVERT(DATETIME, '2012-04-30T19:01:45');
SET LANGUAGE FRENCH;
SELECT CONVERT(DATETIME, '20120430');
SELECT CONVERT(DATETIME, '2012-04-30T19:01:45');
SET LANGUAGE BRITISH;
SELECT CONVERT(DATETIME, '20120430');
SELECT CONVERT(DATETIME, '2012-04-30T19:01:45');
SET DATEFORMAT DMY;
SELECT CONVERT(DATETIME, '20120430');
SELECT CONVERT(DATETIME, '2012-04-30T19:01:45');
因此,我强烈建议不要让用户输入自由文本日期格式(或者您自己使用不可靠的格式),而是控制您的输入字符串并确保它们遵守这些安全格式之一。那么无论用户有什么设置或基础区域设置是什么,您的日期将始终被解释为他们打算成为的日期。如果您当前让用户在表单上的文本字段中输入日期,请停止这样做并实现日历控件或至少一个选择列表,以便最终控制传递回 SQL Server 的字符串格式。
有关一些背景知识,请阅读 Tibor Karaszi 的“日期时间数据类型的终极指南”和我的帖子“要踢的坏习惯:错误处理日期/范围查询”。