次の2つ以外の多くの日付/時刻形式otherは、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形式のようにlookする場合がありますが、いくつかの言語では失敗します。
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);
結果:
Die Spracheneinstellung wurde auf Deutschgeändert。
メッセージ242、レベル16、状態3
Bei der Konvertierung eines varchar-Datentyps in einen datetime-Datentyp liegt der WertaußerhalbdesgültigenBereichs。
Leparamètrede langue estpasséàFrançais。
メッセージ242、レベル16、状態3
La conversion d'un type dedonnéesvarchar en type dedonnéesdatetimecrééune valeur hors limites。
さて、これらは、英語で、月と日を入れ替えて、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ではなく、 "Nice"であり、転置が修正されます。また、SET DATEFORMAT ydm;
で同様のエラーが発生する場合があります-そうではありませんjust言語のこと、それはこれらの破損が発生するより一般的なシナリオであり、時々それらがエラーではないために常に気付かれるわけではなく、8月7日が7月8日になっただけで誰もいない気づいた。)
だから、質問:
安全ではない形式がたくさんあることを知ったので、言語と日付形式の組み合わせを考慮して安全な他の形式はありますか?
ドキュメント では、安全な形式は質問の最初に示したものだけであることを明確に述べています。
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:これは真です。datetime
およびsmalldatetime
の場合。
長いバージョンを読んで、あなたが得るものと同じくらいの証拠について読んでください。
これを説明する抜け穴があります-メインのテキスト本文はyyyyMMdd hh:...
を転置言語または日付形式の解釈から安全な形式として認識できませんが、dateこのような文字列の一部は、dateformat設定によっては検証されません。
通常、Wordでドキュメントを読むだけでは、私とはかなり異なります。あなたは私が少し懐疑的であると言うことができます。また、ここでも言語があいまいです。これは、日付と時刻の組み合わせに関するものであり、スペースを明示的に呼び出さないことを示しているだけです(私が知っている限り、改行の可能性があります)。また、多言語ではない、つまり特定の言語で失敗する可能性があることも記載されていますが、これも正しくないことがすぐにわかります。
したがって、私は言語/日付形式の組み合わせがこの特定の形式を失敗させる可能性がないことを証明しようと試みました。
まず、言語ごとに動的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
文字列から日付や時刻を変換するときに変換に失敗しました。
完全を期すために、4番目の安全な形式がありますが、新しい日付/時刻型(date
、datetime2
、datetimeoffset
)への変換のみが安全です。これらの場合、言語設定は干渉できません:
yyyy-MM-dd hh:mm:...
ただし、onlyは新しいタイプで機能し、古いタイプはまだ大量に使用されているため、使用しないことを強くお勧めします。経験。他のすべての場所にダッシュがあるのはなぜですか(データ型が変更された場合、実際には同じコード内にあります)、ダッシュを削除する必要がありますか?
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);
sameソース文字列が与えられたとしても、変換によってまったく異なる結果が得られました。
März Juli März
日時(yyyyMMdd
)で機能するフォーマットは、また日付およびその他の新しいタイプで常に機能します。だから、私見、いつもそれを使ってください。また、日付/時刻(yyyyMMdd hh:...
)を使用した型の3番目の形式を指定すると、日付コンポーネントが常に読みにくくなる場合でも、実際により一貫性を保つことができます。
今、私が文字列について話しているとき、3つの3つの安全な形式を示す習慣を身に付けるには、数年かかります日付の表現。