地球上の文化の多様性のおかげで、私たちはさまざまな日付形式を持っています。数値の日付には、month-day-year、day-month-year、およびyear-month-dayがあります。短いフォーマットと長いフォーマットもあります。日付は時間と混合することができますが、これは別の話です。この現実は私たちの仕事を追っています。そのため、SQLの日付形式は簡単に作成できるものではありません。
フィリピンでは、月-日-年と日-月-年の2つの形式を使用しています。月-日-年は、数値の日付の一般的な形式です。ただし、日付形式が長い場合は、日-月-年と月-日-年を同じ意味で使用します。
職場では、月-日-年以外のSQLServerの日付形式の設定に遭遇したことはありません。ただし、データ交換およびExtract-Transform-Load(ETL)プロジェクトのレポートとファイルは異なります。個人的な好みのためにステーションでそれを変更するユーザーは言うまでもありません!これらすべてのシナリオで、それらを適切に処理しないことは破るレシピです。
アプリはさまざまな文化に対応していますか?これは、これらのさまざまなSQL日付形式を処理する場合の、もう1つのレベルの複雑さと問題です。この記事では、これらすべての種類と例を扱うための標準について説明します。最後まで読んでください!ただし、先に進む前に、SQLServerが日付を格納する方法について少し回り道をしてみましょう。
SQLServerが日付を保存する方法
当ててみて。 SQL Serverは03/29/202121:35をデータベースにそのまま保存しますか? 2021-03-29はどうですか?それらはフォーマットされた文字列として保存されていますか? Microsoftからのこのドキュメントに基づくと、このようなものではありません。
たとえば、DATEデータ型を考えてみましょう。 3バイト整数として格納されます。
どうやってわかりますか?
そうですね、Microsoftはそうだと言っていますが、それ以上の情報は提供していません。確実にわからないという意味ではありません。まず、DATEデータ型の最小値は01/01/0001または1月1日、西暦1年または西暦です。これを整数に変換するには、次のように、最初にその日付をVARBINARYに変換します。
SELECT CAST(CAST('01/01/0001' AS DATE) AS VARBINARY(3))
結果は0x000000 16進形式。この値から、1CEの1月1日の整数値が0であることがわかります。これは最小のDATE値であるため論理的です。
さて、1日進みます。
SELECT CAST(CAST('01/02/0001' AS DATE) AS VARBINARY(3)) -- January 2, 1 CE
結果は0x010000 。これは少しトリッキーですが、この投稿は私たちにアイデアを与えました。私たちはそれを私たちが見ているように扱うことはできません。バイトが逆になり、実際の16進値は 0x000001 。 16進数について少し知っている場合は、これが1に等しいことを知っています。これは、開始点である1月1日1CEから1日です。
それでは、最近の日付である2021年3月29日を試してみましょう。
SELECT CAST(CAST('03/29/2021' AS DATE) AS VARBINARY(3))
結果は0x55420B 。逆にすると0x0B4255になります 。今回はそれを見ても価値がわかりません。したがって、整数として1を掛けます。
SELECT 0x0B4255 * CAST(1 AS INT)
結果は737,877 。これは、1CEの1月1日からの日数です。 DATEDIFFで確認しましょう。
SELECT DATEDIFF(DAY,CAST('01/01/0001' AS DATE),CAST('03/29/2021' AS DATE))
結果は同じです: 737,877 日々。とてもかっこいい!
結論:フォーマットされた日付はプレゼンテーションのみを目的としています
これが、SQLServerがDATEデータ型を格納する方法です。 DATETIME、SMALLDATETIME、およびDATETIME2では異なりますが、整数として格納されます。 SQL Serverは、開始点からの期間を計算し、私たち全員が理解できる日付を表示します。
SQL Server Management Studio、dbForge Studio for SQL Server、またはアプリのいずれで見ても、2021年3月29日は単なるプレゼンテーションです。地域または言語を変更すると、保存されている値 0x55420B 同じままです。
これで、日付が文字列として保存されないことがわかりました。 特定の形式で日付を保存することを忘れることができます 。それはとにかくそれがどのように機能するかではありません。代わりに、SQLでさまざまな方法を調べて、アプリに必要な日付をフォーマットしてみましょう。
日付をフォーマットする4つの簡単な方法
次のSQL日付関数を調べてみましょう。
- CONVERT関数
- 言語を設定
- 日付形式の設定
- FORMAT関数
SQLクエリフォーマッタを使用することもできます。
1。 CONVERT関数
CONVERTは、日付の書式設定にも使用できるデータ変換関数の1つです。図1に例を示します。
CONVERTの最初の2つの引数は、ターゲットデータ型と日付値です。 3つ目はオプションですが、日付にも適用されます。数値は、日付から文字列への変換中に使用するSQL日付形式のスタイルです。
図1では、日本は区切り文字としてスラッシュを使用した年月日形式を使用しています。ドイツでは、区切り文字としてドットを使用して日-月-年を使用しています。英国とフランスはドイツと同じシーケンスを使用しますが、区切り文字としてスラッシュを使用します。米国のみが、区切り文字としてハイフンを使用した月日年を使用しています。
SQLでは、DATETIME式をDATEに変換することもできます。
SQLのCONVERT日付形式スタイルの完全なリストについては、Microsoftからのこのリファレンスを確認してください。
2。言語の設定
この設定は、セッションに適用される言語を指定します。日付形式とシステムメッセージに影響します。言語を設定するときは、SET DATEFORMAT設定も暗黙的に適用します(後で処理します)。
とりあえず、図2の例を確認しましょう。言語設定をリトアニア語に変更してから、英語に戻します。
図2を見てください。リトアニアの日付形式は年-月-日です。別の日付を試すときはいつでも、長い日付には常に月の前の「m。」と日の後の「d。」が含まれます。月の最初の文字と曜日の名前も大文字ではありません。他の言語設定では異なりますが、要点はわかります。
SET LANGUAGEの詳細については、Microsoftのこのリファレンスを確認してください。
3。日付形式の設定
この設定では、日付文字列を解釈するための月、日、年の順序が設定されます。これは、SETLANGUAGEによって行われた暗黙の日付形式設定をオーバーライドします。これが図3の例です。
図3では、コードはDMYまたは日-月-年の形式を使用しています。これらの設定では、日付変数に設定された日付値はすべてこのパターンに従う必要があります。 30/03/2021はこの形式に一致しますが、31は有効な月ではないため、03/31/2021はエラーをトリガーします。
したがって、ロジックが別の形式を前提として動作している場合、日付形式を変更するとアプリが破損する可能性があります。
SET DATEFORMATの詳細については、Microsoftからのこのリファレンスを確認してください。
4。 FORMAT関数
利用可能なすべてのフォーマットオプションの中で、これが最も柔軟性があります。 FORMATは、SQLServerがインストールされているサーバー上の.NetFrameworkの存在に依存しているため、.Netでの日付の書式設定についても同様です。ただし、これがこのオプションの欠点です。
C#で行うのと同じように、FORMATは日付値とフォーマット文字列を取ります。図4にいくつか例を示しましょう。
.Netと同様に、SQL Serverでは、さまざまな区切り文字を使用して日付をフォーマットできます。また、月、日、年をどこにでも配置できます。次に、文化情報を取得し、その日付形式を使用できます。
FORMATの詳細と例については、Microsoftからのこのリファレンスを確認してください。
ここで、日付をフォーマットする4つの方法とさまざまな日付フォーマットを特定しました。文字列を日付に変換するときに常に機能する標準形式はありますか?
ISO 8601 –変換に使用できる最もポータブルでエラーのないSQL日付形式
ISO 8601は、1988年から存在しています。これは、日付と時刻に関連するデータの交換における国際標準です。 。
日付形式スタイルの1つとしてCONVERT関数でも使用できます。スタイル126および127はISO8601に準拠しています。
ポータブルでエラーのない理由は何ですか?
非ISO8601形式の問題
例を使用して、非ISO8601の問題を示しましょう。
DECLARE @d VARCHAR(10) = '03/09/2021';
SET LANGUAGE Italian;
SELECT FORMAT(CONVERT(DATETIME, @d),'D')
SET LANGUAGE English
SELECT FORMAT(CONVERT(DATETIME, @d),'D')
SET DATEFORMAT DMY
SELECT FORMAT(CONVERT(DATETIME, @d),'D')
SET DATEFORMAT MDY
SELECT FORMAT(CONVERT(DATETIME, @d),'D')
日付のロケールに応じて、@dを2021年3月9日または2021年9月3日と解釈できます。どちらがどちらかはわかりません。そこに問題があります。
以下の図5の結果を確認してください:
SQL Serverでさえ、それを確実に認識していません!
最悪の場合、この種のシナリオは、前の図3で起こったのと同じようにアプリを壊す可能性があります。この状況は、多文化ユーザーを扱うアプリにとっては問題があります。
ISO 8601はこれを支援できますか?
ISO8601を使用したフォーマットの問題への対処
ISO8601形式yyyyMMdd MM / dd / yyyyの代わりに使用されます 図6で結果を確認します:
使用する言語と日付形式の設定に関係なく、常に3月9日です。これは、データ交換やシステム統合に最適です。ユーザーがステーションに別の日付形式を使用している場合も、問題はありません。
日付を文字列に変換して戻す必要がある場合は、ISO8601を使用してください。
SQLServerのISO8601には、次の2つの種類があります。
- YYYYMMDD 日付のみです。
- YYYY-MM-DDTHH:MM:SS 日付と時刻の組み合わせの場合、Tは日付と時刻の間の区切り文字です。
アプリからSQLServerへの日付形式を処理するその他の方法
1。アプリで日付認識コントロールを使用する
フォームに日付を入力するようにユーザーに依頼するときは、フリーテキストを使用させないでください。有効な値からのみ選択できる日付コントロールを使用してください。
2。必要な場合にのみ別の形式に変換する
日付を文字列に、またはその逆に変換し続けないでください。呼び出し元のアプリのネイティブのDateまたはDateTimeデータ型を使用します。何らかの理由でそれらを変換する必要がある場合は、ISO8601を使用してください。
3。該当する場合は、アプリのスタートアップで日付/時刻、タイムゾーン、カルチャを設定します
アプリが固定の日付形式を使用していて、ユーザーが日付形式を微調整するのが好きな場合は、アプリケーションの起動時に両方を修正できます。アプリに必要なものを明示的に設定します。ネットワーク管理者がこれらの設定をロックできると、はるかに優れています。
要点
では、さまざまなSQL日付形式の処理は圧倒的ですか?それでもそのように見つけても非難することはできませんが、不可能ではないことがわかりました。
これが私たちがカバーしたものです:
- SQLの日付は整数として保存されます 。私たちの目で見るものは、SQLServerの設定に基づいてすでにフォーマットされています。言語と日付の形式を何度変更しても、保存される値は同じままです。 特定の形式で日付を保存することを考えるのは無意味です。
- 日付をフォーマットするには、次の4つの方法があります。変換 、言語の設定 、 SET DATEFORMAT 、およびフォーマット 。
- 日付を文字列に、またはその逆に変換する必要がある場合は、ISO8601形式を使用してください 。
- 日付形式を処理する方法は他に3つあります。
- 日付認識コントロールの使用 アプリ内;
- 必要な場合にのみ日付を文字列に変換する;
- 必要に応じて、起動時に必要なタイムゾーン、文化、サーバーの日付/時刻を設定する 。
これはあなたや他の人にとって役立つと思いますか?次に、この記事をお気に入りのソーシャルメディアプラットフォームで共有してください。