declare @str_datetime varchar(50)
set @str_datetime='30-04-2012 19:01:45' -- 30th April 2012
declare @dt_datetime datetime
select @dt_datetime=@str_datetime
这会出现以下错误:
Msg 242,Level 16,State 3,Line 4
转换varchar 数据类型为日期时间数据类型导致超出范围的值。
我的问题是SQL Server如何决定使用哪种格式进行隐式日期时间转换?
答案 0 :(得分:26)
这取决于多种因素 - 操作系统的区域设置,当前用户的语言和日期格式设置。默认情况下,Windows使用US English
,用户的设置为US English
和MDY
。
但是这里有一些例子来说明这是如何改变的。
用户正在使用BRITISH语言设置:
-- works:
SET LANGUAGE BRITISH;
SELECT CONVERT(DATETIME, '30-04-2012 19:01:45');
-- fails:
SELECT CONVERT(DATETIME, '04/13/2012');
GO
(错误)
Msg 242,Level 16,State 3,Line 5
转换varchar数据 键入日期时间数据类型会导致超出范围的值。
用户正在使用Français:
-- 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éesvarcharen typededonnéesdatetimeacrééunevaleur hors 限制一个。
用户再次使用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 typededonnées varchar en typededonnéesdatetimeacrééunevaleur 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
(错误)
Msg 242,Level 16,State 3,Line 2
转换varchar 数据类型为日期时间数据类型导致超出范围的值。
您最好的选择是使用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的"The ultimate guide to the datetime datatypes"和我的帖子"Bad Habits to Kick : Mis-handling date / range queries."
答案 1 :(得分:1)
默认情况下,SQL Server的日期格式为美国日期格式 MM / DD / YY,除非已安装SQL Server的本地化版本。 此设置适用于需要此应用程序的应用程序 以确保使用日期的方式部署功能 并在所有平台和位置以相同的格式插入 使用应用程序的位置。
但是,在某些情况下,日期必须是DD / MM / YY格式,因为 许多国家/地区使用此格式而不是美国的默认格式 MM / DD / YY。这对于国际申请尤其是一个问题 分布在世界各地。
所以你需要做的就是事先设置日期格式:
SET DATEFORMAT dmy
GO
然后你的查询就可以了。
答案 2 :(得分:1)
您还可以更改每个登录和/或每个未来添加登录的默认日期格式(无需在每个会话中执行“SET DATEFORMAT”。
您进入SQL Management Studio / Security / Logins。右键单击登录,然后单击属性。您将在底部看到“默认语言”。
如果您想确保将来添加的任何登录获得“好”语言。右键单击服务器根目录,然后单击“属性和高级”页面。还有一个选项“默认语言”,用于新创建的登录。