日期转换和文化:DATE和DATETIME之间的差异

Shn*_*ugo 6 t-sql sql-server datetime casting date

我已经从字符串中写了很多关于datedatetime转换的答案.生活在一个讲德语的国家,我习惯于处理非us_english日期格式,我习惯使用安全文字(我更喜欢ODBC格式),我从不使用CONVERT第三个参数.这不是问题,请不要在这方面提供答案......

通常人们可以读到,格式yyyy-mm-dd是标准的(ISO8601,ANSI,无论如何),因此文化独立.

今天我必须编辑其中一个较旧的答案,正如我在那里所说,观察到的行为取决于其他东西.

问题是:

为什么(如果有原因)DATE和之间存在差异DATETIME

...至少在我的环境中,目前是SQL Server 2014(12.0.4237.0).

我希望,之前没有问过......

试试这个:

没问题,DATE按预期工作

SET LANGUAGE ENGLISH;
DECLARE @dt DATE='2017-01-13'; 
SELECT @dt;
SELECT CAST('2017-01-13' AS DATE);
SELECT CONVERT(DATE,'2017-01-13'); --no culture / format specified
GO
SET LANGUAGE GERMAN;
DECLARE @dt DATE='2017-01-13';
SELECT @dt;
SELECT CAST('2017-01-13' AS DATE);
SELECT CONVERT(DATE,'2017-01-13'); 
Run Code Online (Sandbox Code Playgroud)

但是现在检查一下 DATETIME

--No problem here:
SET LANGUAGE ENGLISH;
DECLARE @dt DATETIME='2017-01-13'; 
SELECT @dt;
SELECT CAST('2017-01-13' AS DATETIME);
SELECT CONVERT(DATETIME,'2017-01-13'); 
GO

--breaks, due to the "13" and would deliver a wrong result (even worse), if the "day" was not more than "12":
SET LANGUAGE GERMAN;
DECLARE @dt DATETIME='2017-01-13'; 
SELECT @dt;
SELECT CAST('2017-01-13' AS DATETIME);
SELECT CONVERT(DATETIME,'2017-01-13'); 
Run Code Online (Sandbox Code Playgroud)

这是一个错误,目的还是只是粗暴?

mar*_*c_s 6

DATETIME(旧版型)的ISO-8601以某种方式"破坏"或"改编"(取决于您是将其视为错误还是功能) - 您需要使用YYYYMMDD(没有任何破折号)使其工作而不管语言设置.

对于DATEDATETIME2(n)数据类型,这已得到修复,并且YYYY-MM-DD将始终正确解释"正确的"ISO-8601格式.

-- OK because of "adapted" ISO-8601
SET LANGUAGE GERMAN;
DECLARE @dt DATETIME='20170113'; 

SELECT @dt;

SELECT CAST('20170113' AS DATETIME);
SELECT CONVERT(DATETIME, '20170113'); 

-- OK because of DATETIME2(n)
SET LANGUAGE GERMAN;
DECLARE @dt2 DATETIME2(0) = '2017-01-13'; 

SELECT @dt2;

SELECT CAST('2017-01-13' AS DATETIME2(0));
SELECT CONVERT(DATETIME2(0), '2017-01-13'); 
Run Code Online (Sandbox Code Playgroud)

这是DATETIME类型的怪癖(而不是唯一的......) - 只需注册它,了解它 - 并继续前进(意思是:不再使用DATETIME- 使用DATEDATETIME2(n)改为 - 使用起来更好!): - )