LANGUAGE 및 DATEFORMAT은 어떤 날짜 / 시간 리터럴 형식으로 안전합니까?


24

많은 날짜 / 시간 형식 증명하기 쉬운 다른 다음과 같은 두 가지 때문에 SET LANGUAGE, SET DATEFORMAT 또는 로그인의 기본 언어에 대한 잘못된 해석에 취약보다를 :

yyyyMMdd                 -- unseparated, date only
yyyy-MM-ddThh:mm:ss.fff  -- date dash separated, date/time separated by T 

T가없는이 형식조차도 유효한 ISO 8601 형식처럼 보일 수 있지만 여러 언어에서 실패합니다.

DECLARE @d varchar(32) = '2017-03-13 23:22:21.020';

SET LANGUAGE Deutsch;
SELECT CONVERT(datetime, @d);

SET LANGUAGE Français;
SELECT CONVERT(datetime, @d);

결과 :

Spracheneinstellung 님이 Deutsch geändert에 있습니다.

메시지 242, 수준 16, 상태 3
Bei der Konvertierung eine vartime-Datentyps에서 날짜 시간 -Datentyp liegt der Wert außerhalb des gültigen Bereichs에서.

Le paramètre de langue est passé à Français.

메시지 242, 수준 16, 상태 3
La 변환 d' un 유형 de données varchar en 유형 de données 날짜 시간 crée un valeur hors limits.

이제는 영어로, 달과 일을 바꾼 것처럼 날짜 구성 요소를 공식화하는 것처럼 실패합니다 yyyy-dd-mm.

DECLARE @d varchar(32) = '2017-13-03 23:22:21.020';

SET LANGUAGE us_english;
SELECT CONVERT(datetime, @d);

결과:

메시지 242, 수준 16, 상태 3
varchar 데이터 형식을 날짜 / 시간 데이터 형식으로 변환하면 범위를 벗어난 값이 발생했습니다.

(이것은 "좋은"는 당신과 수정에 당신을위한 전치 마이크로 소프트 액세스, 아니다 또한, 유사한 오류가 일부 경우에 발생할 수 있습니다. SET DATEFORMAT ydm;- 그렇지 않은 단지 언어 것은, 단지 더 일반적인 시나리오이있어 그 오류가 발생하는 경우가 있습니다. 때로는 오류가 아니기 때문에 항상 눈에 띄는 것은 아닙니다. 8 월 7 일이 7 월 8 일이되어서 아무도 눈치 채지 못했습니다.)

따라서 질문 :

안전하지 않은 형식이 많이 있음을 알았으므로 언어 ​​및 날짜 형식 조합을 고려하여 안전한 다른 형식이 있습니까?

답변:


26

에서 문서 , 아주 명시 적으로 유일한 안전 형식 내가 바로 문제의 시작에서 시연 그들이다 것을 주장한다 :

yyyyMMdd                 -- unseparated, date only
yyyy-MM-ddThh:mm:ss.fff  -- date dash separated, date/time separated by T 

그러나 최근에 어떤 언어 또는 날짜 형식 설정에도 동일하게 적용되는 세 번째 형식이 있음에 주목했습니다.

yyyyMMdd hh:mm:ss.fff    -- unseparated date, no T separator

TL; DR : 사실입니다. 들어 datetimesmalldatetime.

더 긴 버전과 더 많은 증거를 읽으십시오.


이것을 설명하는 허점이 있습니다-본문이 yyyyMMdd hh:...전치 된 언어 또는 날짜 형식 해석으로부터 안전한 형식 으로 인식하지 못하는 경우, 그러한 문자열 의 날짜 부분이 날짜 형식 설정에 따라 유효성이 검사되지 않는다는 약간의 희미 함이 있습니다 .

여기에 이미지 설명을 입력하십시오

일반적으로 문서를 그 단어로 가져 오는 것과는 다릅니다. 내가 약간 회의적이라고 말할 수 있습니다. 그리고 언어도 여기에서 모호합니다-이것은 공간을 명시 적으로 호출하지 않고 날짜와 시간의 조합에 관한 것입니다 (내가 아는 모든 것의 캐리지 리턴 일 수 있음). 또한 다국어가 아니기 때문에 특정 언어에서는 실패 할 수 있지만 곧 틀린 것임을 곧 알게 될 것입니다.

따라서 언어 / 날짜 형식의 조합으로 인해이 특정 형식이 실패하지 않음을 증명하기 시작했습니다.

먼저 각 언어마다 작은 동적 SQL 블록을 만들었습니다.

EXEC sys.sp_executesql @sql, N'@lang sysname', N'us_english';

이렇게하면 다음과 같은 34 행의 출력이 생성됩니다.

EXEC sys.sp_executesql @sql, N'@lang sysname', N'us_english';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'Deutsch';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'Français';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'日本語';
...
EXEC sys.sp_executesql @sql, N'@lang sysname', N'简体中文';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'Arabic';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'ไทย';
EXEC sys.sp_executesql @sql, N'@lang sysname', N'norsk (bokmål)';    

출력을 새 쿼리 창에 복사하고 그 위의 코드를 생성했습니다.이 코드는 동일한 날짜 (3 월 13 일)를 적어도 한 경우에 13 월 3 일로 변환하려고합니다.

DECLARE @sql nvarchar(max) = N'
SET LANGUAGE @lang;
SET DATEFORMAT ydm;
SELECT @@LANGUAGE, CONVERT(datetime, ''20170313 23:22:21.020'');';

아니요, 모든 언어는에서 찾을 수 있습니다 ydm. 다른 모든 형식과 모든 날짜 / 시간 데이터 형식도 시도했습니다. 3 월 13 일까지 34 번의 성공적인 전환

따라서 @AndriyM과 @ErikE는 실제로 세 번째 안전한 형식이 있음을 인정합니다. 나는 미래의 게시물에 대해 이것을 명심하지만 많은 곳에서 다른 두 가지에 대해 드럼을 두들 겼습니다. 나는 그들을 모두 사냥하고 지금 수정하지는 않을 것입니다.


확장하면, 당신은 이것이 안전 할 것이라고 생각할 것입니다.

yyyyMMddThh:mm:ss.fff    -- unseparated date, T separator

나는 모든 언어에서 다음과 같은 것을 얻을 것이라고 생각합니다.

메시지 241, 수준 16, 상태 1, 줄 8
문자열에서 날짜 및 / 또는 시간을 변환 할 때 변환에 실패했습니다.


완성도를 들어,이 네 번째 안전 형식이지만 새로운 날짜 / 시간 형식으로 변환 만 안전 ( date, datetime2, datetimeoffset). 이 경우 언어 설정을 방해 할 수 없습니다.

yyyy-MM-dd hh:mm:...

그러나 새로운 유형 에만 작동하고 이전 유형은 여전히 ​​많은 경험을 가지고 있기 때문에 사용하지 않는 것이 좋습니다 . 다른 곳에서 (또는 데이터 유형이 변경되면 실제로 동일한 코드에서) 대시를 제거 해야하는 이유는 무엇입니까?

SET LANGUAGE Deutsch;
DECLARE @dashes char(10) = '2017-03-07 03:34';
DECLARE @d date = @dashes, @dt datetime = @dashes, @dt2 datetime2 = @dashes;

SELECT DATENAME(MONTH,@d), DATENAME(MONTH,@dt), DATENAME(MONTH,@dt2);

소스 문자열 이 동일 하더라도 변환 결과가 크게 다릅니다.

März    Juli    März

날짜 시간 ( yyyyMMdd)에 작동하는 형식 항상 날짜 및 다른 새 유형 에도 작동합니다. 따라서 IMHO, 항상 사용하십시오. 날짜 / 시간 ( yyyyMMdd hh:...)이있는 유형에 대한 세 번째 형식이 주어지면 날짜 구성 요소를 항상 읽을 수없는 경우에도 실제로 일관성을 유지할 수 있습니다.


이제 날짜의 문자열 표현에 대해 이야기 할 때 세 가지 안전한 형식 을 시연하는 습관을들이는 데 몇 년이 걸렸습니다 .


향후 릴리스에서 SQL Server에 새 언어를 추가 할 때 세 번째 형식 안전하지 않을 수 있습니까?
Kuba Wyrostek

@Kuba Microsoft가 이에 대한 교훈을 얻었을 것이라고 확신합니다. 누군가이 모든 언어가 yyyy-dd-MM을 해석하도록 결정하지 못했습니다. 지구상의 어느 누구도 의도적으로 사용하지 않은 형식입니다.
Aaron Bertrand
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.