LANGUAGEおよびDATEFORMATで安全な日付/時刻リテラル形式は何ですか?


24

それは多くの日付/時刻形式ことを実証することは容易であるほか、以下の2以上が原因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);

結果:

ドイツ連邦共和国の金型について。

メッセージ242、レベル16、状態3
備デア・Konvertierung eines varchar型-Datentyps einenのdatetime-Datentyp liegtデア・ワートaußerhalbデgültigenBereichsインチ

フランセのラングパレドゥラングエストパセ。

Msg 242、レベル16、状態3
変換の種類日付の種類と日付の種類の制限なし。

今、これらは、英語で、月と日を置き換えて、次の日付コンポーネントを定式化したかのように失敗します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データ型からdatetimeデータ型への変換の結果、範囲外の値が生じました。

(これはMicrosoft Accessではありません。これはあなたにとって「いい」ものであり、転位を修正します。また、場合によっては同様のエラーが発生する可能性があります。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 

しかし、最近、言語や日付形式の設定に影響されない3番目の形式があることに気付きました。

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

TL; DR:これは本当です。以下のためdatetimesmalldatetime

長いバージョンを読んで、これから入手する証拠とほぼ同じくらいの証拠を読んでください。


これを説明する抜け穴があります-メインテキスト本文はyyyyMMdd hh:...、転置された言語または日付形式の解釈から安全な形式として認識できませんが、そのような文字列の日付部分はdateformat設定に応じて検証されないという少しの宣伝文句があります:

ここに画像の説明を入力してください

通常、ドキュメントを単にその言葉で取り上げるのは私とは異なります。あなたは私が少し懐疑的だと言うことができます。そして、言語もここではあいまいです-これは、これが日付と時刻の組み合わせに関するものであり、スペースを明示的に呼び出さないことを示しています(私が知っている限り、キャリッジリターンである可能性があります)。また、それは多言語ではない、つまり特定の言語では失敗する可能性があると言っていますが、まもなくそれも間違っていることがわかります。

そのため、言語/日付形式の組み合わせによってこの特定の形式が失敗することはないことを証明することにしました。

最初に、言語ごとに動的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)';    

その出力を新しいクエリウィンドウにコピーし、その上でこのコードを生成しました。このコードは、少なくとも1つのケースで、同じ日付(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には、確かに3番目の安全な形式があることを認めています。将来の投稿のためにこれを念頭に置いていますが、他の2つのドラムについては非常に多くの場所で叩いています。


拡張すると、これは安全だと思うでしょうが、そうではありません:

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

すべての言語で、これは次のものと同等になると思います。

メッセージ241、レベル16、状態1、行8の
変換は、文字列から日付や時刻を変換するときに失敗しました。


完全性のために、そこに第四の安全なフォーマットであり、それは、新しい日付/時刻型への変換のためにのみ安全です(datedatetime2datetimeoffset)。これらの場合、言語設定は干渉できません。

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)で機能する形式は、日付およびその他の新しいタイプで常に機能します。だから、私見、常にそれを使用してください。そして、日付/時刻(yyyyMMdd hh:...)を持つ型の3番目の形式が与えられると、日付コンポーネントが常に少し読みにくくなる場合でも、これにより実際にあなたはより一貫性を持たせることができます。


日付の文字列表現について話しているときに、3つの安全な形式を実証する習慣を身に付けるために、与えられようと受けとろうと数年かかるだけです。


将来のリリースでSQL Serverに新しい言語が追加されると、3番目の形式が安全でなくなる可能性はありませんか?
キューバWyrostek

@Kuba Microsoftがこれについての教訓を学んだとかなり確信しています。誰かがこれらの言語のすべてにyyyy-dd-MMを解釈させるというかなり下手な決定を下しました。
アーロンバートランド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.