SQL ServerのDateTime2とDateTime


762

どれ:

SQL Server 2008以降で日付と時刻を格納するための推奨される方法は何ですか?

精度の違いを認識しています(おそらくストレージスペースも)が、現時点ではそれらを無視しています。何をいつ使用するかに関するベストプラクティスドキュメントはありますか、それとも単に使用するdatetime2だけなのでしょうか?

回答:


641

以下のためのMSDNドキュメント日時が使用することをお勧めしますDATETIME2を。ここに彼らの推薦があります:

使用しtimedatedatetime2datetimeoffset新しい仕事のためのデータ型を。これらの型は、SQL標準に準拠しています。彼らはよりポータブルです。 timedatetime2そしてdatetimeoffset より多くの秒の精度を提供します。 datetimeoffsetグローバルに展開されたアプリケーションにタイムゾーンのサポートを提供します。

datetime2は、日付範囲が大きく、デフォルトの小数精度が大きく、オプションでユーザー指定の精度があります。また、ユーザー指定の精度によっては、使用するストレージが少なくなる場合があります。


46
datetime2では精度が向上していますが、一部のクライアントは日付、時刻、またはdatetime2をサポートしておらず、文字列リテラルへの変換を強制しています。精度よりも互換性に関心がある場合は、datetimeを使用してください
FistOfFury

4
別のオプションは、互換性のために日時に変換された列でインデックス付きビューを使用することです。ただし、アプリをビューにポイントできる必要があります。
TamusJRoyce

9
DATETIMEOFFSETを使用したタイムゾーンのサポートは誤称です。タイムゾーンではなく、特定の時点のUTCオフセットのみを保存します。
Suncat2000

6
@Porad:「SQL標準」であるため、「移植性が高まる」ことの利点は何ですか?それは、別のRDBMSへの「ポート」で読み取り/保守が大幅に少ないコードを大幅に作成することに加えて、そのコードの存続期間中に発生する可能性はほとんどありません。おそらくMicrosoftが提供するSQL Serverツールとドライバー(もしあれば)DateTime2以外に、タイプ(またはその他のSQL Server)の特定のビットレベル表現に実際に依存するアプリはありますかその件について入力してください)?なぜ私が質問しているのかについては、以下の私の7/10/17回答の短所を参照してください
Tom

2
@Adam Porad:また、これらのメリットはすべて(エンジニアリングまたは科学アプリ以外では)おそらく不要であり、メリットを失う価値はあまりありません。必要になる可能性がはるかに高くなります。暗黙的または明示的に変換するはるかに簡単な(回避策を考慮しても)機能加算、減算、最小値、最大値、平均値の浮動小数点数値(該当する場合は日数、最小日時からの小数日)値。詳細については、下記の私の7/10/17回答の短所を参照してください。
トム

493

DATETIME2DATETIMEタイプは「0001/01/01 」から「9999/12/31 」までの日付範囲を持ちますが、タイプは年1753-9999のみをサポートします。

また、必要に応じて、 DATETIME2時間を正確にすることができます。DATETIMEは3 1/3ミリ秒に制限されていますが、DATETIME2正確には100nsまで可能です。

どちらのタイプも System.DateTime .NETでれます-違いはありません。

選択肢があれば、DATETIME2なるべく使用することをお勧めします。を使用して何の利点も見ていませんDATETIME(下位互換性を除く)-問題が少なくなります(日付が範囲外であり、そのような手間がかかります)。

さらに、日付のみが必要な場合(時刻部分なし)はDATEを使用します-日付も同じで、DATETIME2スペースも節約できます。:-)同じことが時間のみに適用されます-使用してくださいTIME。それがこれらのタイプの目的です!


158
.NET DateTime値をパラメーターとしてSqlCommandに追加するときは注意してください。これは、古いdatetime型であると想定し、1753〜9999年の範囲外のDateTime値を書き込もうとするとエラーが発生するためです。 SqlParameterのタイプをSystem.Data.SqlDbType.DateTime2として明示的に指定しない限り。とにかく、datetime2は、.NETのDateTime型に格納できる任意の値を格納できるため、優れています。
Triynko

10
@marc_s-それはnullの目的ではありませんか?
JohnFx

8
@JohnFX-ここでは少し遅れますが、datetimeをnullに設定しません。Nullable <datetime>またはdatetimeを使用しますか?これはnullをうまく処理します-そして、プロシージャへのマッピングでは、単にparam.value = someDateTime ?? DBValue.Nullその不幸なことは後に、私たちは数とデータ型と立ち往生している-ちょうどそう「一般的な」と思われる。)
MSFT -アダムTuliper

69
笑、自分のコメント(1年以上前に作成されたもの)だと気づく前に、自分のコメント(上)に賛成票を入れようとしたところです。より正確なSqlDbType.DateTime2に明示的に設定しない限り、SqlParametersとして渡されたときにデフォルトですべてのDateTime値をTRUNCATEするという.NETフレームワークのばかげた設計決定についても対処しています。正しいタイプを自動的に推論するには、これで終わりです。実際、変更を透過的にする必要があり、精度が低く、効率が低く、範囲が限定された実装を置き換え、元の「日時」型名を保持する必要がありました。stackoverflow.com/q/8421332/88409
Triynko

5
@marc_sそれは何のNullable<DateTime>ためですか?
ChrisW、2015年

207

datetime2は、(古いアプリの互換性)を除いて、ほとんどの面で勝利します

  1. より大きな値の範囲
  2. より良い精度
  3. より小さいストレージスペース (オプションのユーザー指定の精度が指定されている場合)

SQLの日付と時刻のデータ型の比較-datetime、datetime2、date、TIME

次の点に注意してください

  • 構文
    • datetime2 [(小数秒の精度=>ストレージサイズを下回る)]
  • 精度、スケール
    • 100 nsの精度で0から7桁。
    • デフォルトの精度は7桁です。
  • 収納サイズ
    • 精度が3未満の場合は6バイト。
    • 精度3および4の場合は7バイト。
    • 他のすべての精度には8バイトが必要です
  • DateTime2(3)の桁数はDateTimeと同じですが、8バイトではなく7バイトのストレージを使用します(SQLHINTS- DateTime Vs DateTime2
  • datetime2に関する詳細情報(Transact-SQL MSDN記事)

画像ソース: MCTS Self-Paced Training Kit(Exam 70-432):Microsoft®SQLServer®2008-Implementation and Maintenance Chapter 3:Tables- > Lesson 1:Creating Tables- > 66ページ


7
統計を+1してくれてありがとう、datetime2素晴らしいです(受賞)
Pankaj Parkar

2
@Iman Abidi:参照した「SQLHINTS- DateTime Vs DateTime2」の記事の2014年9月10日15:51に日付を記入したOskar Berggrenのコメントによると、「datetime2(3)はdatetimeと同じではありません。同じ番号になります。桁数ですが、datetime2(3)の精度は1msですが、datetimeの精度は3.33msです。
トム

1
@PankajParkar:すごい、それほど速くない。下記の17/10/17付けの私の回答の短所セクションをご覧になることをお勧めします。
トム

datetime2使用するストレージスペースが少ないdatetimeのに、より広い範囲と高い精度を実現するにはどうすればよいですか
Dai

107

@marc_sと@Adam_Powardに同意します-今後はDateTime2が推奨される方法です。日付の範囲が広く、精度が高く、使用するストレージは(精度に応じて)以下です。

しかし、議論が失敗したことの1つ...
@Marc_sは次のように述べていますBoth types map to System.DateTime in .NET - no difference there。これは正しいですが、逆は当てはまりません。日付範囲検索を実行する場合は重要です(たとえば、「2010年5月5日に変更されたすべてのレコードを検索してください」)。

.NETのバージョンの Datetime範囲と精度はと似ていますDateTime2。.net Datetimeを古いSQLにマッピングするとDateTime暗黙的な丸めが発生します。古いSQLのDateTime精度は3ミリ秒です。これは11:59:59.997、1日の終わりに到達できる限り近いことを意味します。それ以上の場合は翌日に切り上げられます。

これを試して :

declare @d1 datetime   = '5/5/2010 23:59:59.999'
declare @d2 datetime2  = '5/5/2010 23:59:59.999'
declare @d3 datetime   = '5/5/2010 23:59:59.997'
select @d1 as 'IAmMay6BecauseOfRounding', @d2 'May5', @d3 'StillMay5Because2msEarlier'

この暗黙的な丸めを回避することは、DateTime2に移行する大きな理由です。日付の暗黙的な丸めは明らかに混乱を引き起こします:


14
とにかく一日の「終わり」を見つけようとしないことで、この丸めを回避することもできます。> = 5月5日および<5月6日の方がはるかに安全であり、どのような日付/時刻タイプでも動作します(もちろんTIMEを除く)。また、m / d / yyyyのような地域のあいまいな形式を避けることをお勧めします。
アーロンバートランド14

2
@AaronBertrand-完全に同意しますが、説明する価値があると思われる問題を抱えている質問の数を見てください。
EBarr 2014

1
から20100505に切り替えたのはなぜ5/5/2010ですか?前者の形式は、SQL Serverのどのリージョンでも機能します。後者は壊れます:SET LANGUAGE French; SELECT Convert(datetime, '1/7/2015')おっと:2015-07-01 00:00:00.000
ErikE

1
@EBarr:Re。「DateTime2は、今後推奨される方法です。日付の範囲が広く、精度が高く、使用するストレージが(精度に応じて)同等かそれ以下です。私は強く同意しません。下記の7/10/17付けの私の回答の短所セクションを参照してください。つまり、これらのメリットはおそらく不要であり(エンジニアリング/科学アプリ以外)、メリットを失う価値はありません。必要な可能性がはるかに高く、暗黙的または明示的に浮動小数点数値に変換する(回避策を考慮しても)はるかに簡単です( +、-、および平均の場合のアプリケーションの場合の日数、最小日時以降の分数)値
トム

20

ほとんどすべての回答とコメントは長所に重く、短所に軽いです。これまでのすべての長所と短所と、私が一度だけ言及したか、まったく言及していない重要な短所(以下の#2)の要約です。

  1. 長所:

1.1。よりISO準拠(ISO 8601)(これが実際にどのように機能するかはわかりませんが)。

1.2。より広い範囲(1/1/0001から12/31/9999対1/1 / 1753-12 / 31/9999)(ただし、1753年より前のすべての追加の範囲は、ex。歴史、天文、地質学などのアプリで)。

1.3。.NETのDateTimeTypeの範囲に完全に一致します(ただし、値がターゲットのTypeの範囲と精度の範囲内にある場合は、特別なコーディングなしで前後に変換されます。それ以外の場合、Con#2.1を除き、エラー/丸めが発生します)。

1.4。より高い精度(100ナノ秒、つまり0.000,000,1秒vs. 3.33ミリ秒、つまり0.003,33秒)(ただし、追加の精度は、エンジニアリング/科学アプリなどで使用される場合を除いて、おそらく使用されません)。

1.5。用に設定する場合と同様の(イマンAbidiが主張したように)3.33ミリ秒のように(「同じ」ではない1ミリ秒のように)としての精度をDateTime、より少ないスペース(7 8対バイト)を使用しますが、その後、もちろん、あなたが失うことだろうおそらく2つのうちの1つである精度の利点(もう一方は範囲です)は、不必要な利点である可能性がありますが、最も宣伝されています)。

  1. 短所:

2.1。パラメータを.NETに渡すときは、SQL Server の範囲や精度以外の値を渡す可能性があるかどうかをSqlCommand指定する必要があります。System.Data.SqlDbType.DateTime2DateTimeSystem.Data.SqlDbType.DateTime

2.2。暗黙的に/簡単に浮動小数点数値(最小日時からの日数)に変換して、数値と演算子を使用するSQL Server式で次の操作を行うことはできません。

2.2.1。日数または一部の日数を加算または減算します。注:DateAdd日時のすべてではないにしても複数を考慮する必要がある場合、関数を回避策として使用することは簡単ではありません。

2.2.2。「年齢」の計算のために、2つの日時の差を取ります。注:DateDiff代わりにSQL Serverの関数を単純に使用することはできませんage。2つの日時が偶然に指定された単位のカレンダー/時計の日時境界を越えた場合でも、ほんの一部であっても、ほとんどの人が期待するように計算されないためです。その単位の差は、その単位の1と0の差として返されます。たとえば、1ミリ秒しか離れていない2つの日時のDateDiffinはDay、それらの日時が1である場合、0と1(0)を返します。異なる暦日(つまり、「1999-12-31 23:59:59.9999999」と「2000-01-01 00:00:00.0000000」)。同じ1ミリ秒の日付と時刻を移動して、暦日を越えないようにするとDay、0(日)の「DateDiff」が返されます。

2.2.3。Avg最初に「Float」に変換してから再びに戻すだけで、(集約クエリの)日時を取得しDateTimeます。

注:DateTime2数値に変換するには、次の数式のようにする必要があります。これは、値が1970年以上であることを前提としています(つまり、余分な範囲とさらに217年がすべて失われることを意味します。注:数値のオーバーフローの問題に遭遇する可能性があるため、追加の範囲を可能にするために式を単純に調整することはできません。

25567 + (DATEDIFF(SECOND, {d '1970-01-01'}, @Time) + DATEPART(nanosecond, @Time) / 1.0E + 9) / 86400.0–ソース:「https://siderite.dev/blog/how-to-translate-t-sql-datetime2-to.html

もちろん、あなたも可能性CastへのDateTime最初の(そして必要なバックは再びへの場合DateTime2)がありますが、精度と範囲の(すべての前年の1753年)の利益を失うと思いDateTime2DateTimeprolly 2最大とも同時にprollyです加算/減算/「年齢」(対DateDiff)/ Avg計算の利点のために浮動小数点数値(日数)への暗黙的/簡単な変換を失うときになぜそれを使用するのか疑問を投げかける2つの最も可能性の低いもの私の経験では。

ところで、Avg日時のは重要な使用例です(または少なくともそうする必要があります)。a)日時(共通の基本日時)が期間を表すために使用されている場合に平均期間を取得するために使用する以外に(一般的な方法)、b)平均日付に関するダッシュボードタイプの統計を取得することも役立ちます-時間は、行の範囲/グループの日時列にあります。c)列内の値を監視/トラブルシューティングするための標準(または少なくとも標準である必要がある)アドホッククエリは、有効でなくなる可能性があり、もはや/または非推奨にする必要がある可能性があります。 (利用可能な場合)MinAvgおよびMaxその値に関連付けられた日時スタンプ。


1
逆張りの見方のように-それは方程式のc#側を指し示します。他のすべての「長所」と組み合わせると、人々は自分の痛みを取りたい場所に基づいて良い選択をすることができます。
EBarr 2017

1
@EBarr:私の「 'contrarian view'」の短所#1部分のみが「方程式のc#側を指摘しています」。残り(短所#の2.2.1-2.2.3)は、私が言ったように(のDateTime)はるかに必要とされる利点であり、すべてSQL Serverのクエリとステートメントへの影響に関連しています。
トム

2.2.1について-日付に対して算術演算を行うことは安全ではないと考えられており、常に好ましい方法はDateAddおよび関連する関数を使用することです。これがベストプラクティスです。日付の算術を実行することには重大な欠点があり、そのほとんどが、ほとんどの日付タイプでは機能しません。いくつかの記事: sqlservercentral.com/blogs/...の sqlblog.org/2011/09/20/...
RBerman

@RBerman:Re。「安全でない」:特定の日付タイプでは安全ではありません(DateTime2すでに述べた(オーバーフローの可能性が高いため))。再 「ほとんどの日付タイプでは機能しません」:1つで機能すれば十分であり、ほとんどのアプリのほとんどの日付は、存続期間全体にわたって別の日付タイプに変換する必要はおそらくありません(おそらく、前述のように、DateTime2DateTime(例えば「日付の計算」を行う; P)、それはプログラムだけでなく、広告がアドホック研究は、非算術優しいdate型を使用するように照会していないだけでコーディングすべての余分な価値はないことを考える。。
トム・

15

問題のフィールドにNow()を書き込もうとしているAccess開発者がいる場合、DateTime2は大混乱を引き起こします。Access-> SQL 2008 R2に移行しただけで、すべての日時フィールドがDateTime2として配置されました。爆撃された値としてNow()を使用してレコードを追加します。それは1/1/2012 2:53:04 PMでは問題ありませんでしたが、1/10/2012 2:53:04 PMでは問題ありませんでした。

かつてキャラクターが違いを生んだ。それが誰かを助けることを願っています。


15

smalldatetime、datetime、datetime2(0)、datetime2(7)のストレージサイズ(バイト)と精度の違いを示す例を次に示します。

DECLARE @temp TABLE (
    sdt smalldatetime,
    dt datetime,
    dt20 datetime2(0),
    dt27 datetime2(7)
)

INSERT @temp
SELECT getdate(),getdate(),getdate(),getdate()

SELECT sdt,DATALENGTH(sdt) as sdt_bytes,
    dt,DATALENGTH(dt) as dt_bytes,
    dt20,DATALENGTH(dt20) as dt20_bytes,
    dt27, DATALENGTH(dt27) as dt27_bytes FROM @temp

戻る

sdt                  sdt_bytes  dt                       dt_bytes  dt20                 dt20_bytes  dt27                         dt27_bytes
2015-09-11 11:26:00  4          2015-09-11 11:25:42.417  8         2015-09-11 11:25:42  6           2015-09-11 11:25:42.4170000  8

したがって、ミリ秒単位ではなく秒単位で情報を格納したい場合、datetimeまたはdatetime2(7)の代わりにdatetime2(0)を使用すると、それぞれ2バイトを節約できます。


10

そこに増加させながら精度をしてDATETIME2、いくつかのクライアントがサポートされていない日付時間、またはDATETIME2をして、文字列リテラルに変換することを強制します。具体的には、Microsoftは、これらのデータ型に関する「下位レベル」のODBC、OLE DB、JDBC、およびSqlClientの問題について言及しており、それぞれがどのように型をマップできるかを示すグラフがあります。

精度よりも値の互換性がある場合は、datetimeを使用します


10

古い質問...しかし、まだ誰も述べていない何かをここに追加したい...(注:これは私自身の観察なので、参照を要求しないでください)

フィルター基準で使用すると、Datetime2の方が高速です。

TLDR:

SQL 2016では、正確な時刻を秒単位で格納する必要があったため、10万行のテーブルと日時列ENTRY_TIMEがありました。多くの結合とサブクエリを含む複雑なクエリを実行しているときに、where句を次のように使用した場合:

WHERE ENTRY_TIME >= '2017-01-01 00:00:00' AND ENTRY_TIME < '2018-01-01 00:00:00'

何百もの行がある場合、クエリは最初は問題ありませんでしたが、行数が増えると、クエリは次のエラーを出し始めました。

Execution Timeout Expired. The timeout period elapsed prior
to completion of the operation or the server is not responding.

where句を削除したところ、予想外に、クエリは1秒で実行されましたが、すべての日付のすべての行がフェッチされました。where句を使用して内部クエリを実行すると85秒かかり、where句を使用しない場合は0.01秒かかりました。

日時フィルタリングのパフォーマンスとして、この問題のためにここで多くのスレッドに出くわしました

クエリを少し最適化しました。しかし、私が得た実際の速度は、datetime列をdatetime2に変更することでした。

これで、以前にタイムアウトになった同じクエリの実行時間が1秒未満になりました。

乾杯


9

日付文字列の解釈にdatetimeおよびdatetime2米国以外の使用しているとき、あまりにも異なることができDATEFORMAT、設定を。例えば

set dateformat dmy
declare @d datetime, @d2 datetime2
select @d = '2013-06-05', @d2 = '2013-06-05'
select @d, @d2

これを返す2013-05-06ために(つまり、5月6日)datetime、及び2013-06-05(つまり、6月5日)のためにdatetime2。しかし、とのdateformatセットにmdy両方、@dおよび@d2リターン2013-06-05

このdatetime動作は、MSDNのドキュメントに次のようSET DATEFORMATに記載されているのとは異なります。ISO8601などの一部の文字列形式は、DATEFORMAT設定とは無関係に解釈されます。。明らかに本当ではない!

これに悩まされるまでyyyy-mm-dd、言語やロケールの設定に関係なく、日付は正しく処理されるといつも思っていました。


2
いいえ。ISO 8601の場合、YYYYMMDD(ダッシュなし)を意味していると思います。SET LANGUAGE FRENCH; DECLARE @d DATETIME = '20130605'; SELECT @d;ダッシュでもう一度お試しください。
アーロンバートランド14

1
この規格では、カレンダーの日付表現にYYYY-MM-DD形式とYYYYMMDD形式の両方を使用できます。MSDNはISO 8601仕様のどのサブセットが独立して解釈されるかについてより具体的である必要があると思います!
Richard Fawcett 2014

1
私はそれを知っていますが、SQL Serverではno-dash構文のみが安全です。
アーロンバートランド14

6

この記事によると、DateTime2を使用して同じ精度のDateTimeを使用する場合は、DateTime2(3)を使用するだけです。これにより、同じ精度が得られ、バイト数が1つ少なくなり、範囲が拡張されます。


明確に言うと、これは.NET DateTimeではなく、SQL datetimeと同じ精度です。
Sam Rueby 2015年

それは正しいです、私は誰もが文脈を理解するだろうと思いましたが、それは具体的に述べる価値があります。
jKlaus 2015年

4

私は、もう1つの利点に出くわしましたDATETIME2。それは、Python adodbapiモジュールのバグを回避します。これdatetimeは、DATETIME列にゼロ以外のマイクロ秒を持つ標準ライブラリ値が渡された場合に爆発しますが、列がとして定義されてDATETIME2いる場合は正常に動作します。


0
Select ValidUntil + 1
from Documents

上記のSQLは、DateTime2フィールドでは機能しません。返され、エラー「オペランドタイプの競合:datetime2はintと互換性がありません」

翌日を取得するために1を追加することは、開発者が何年もの間日付で行ってきたものです。現在、Microsoftには、この単純な機能を処理できない非常に新しいdatetime2フィールドがあります。

「古いタイプよりも悪いこの新しいタイプを使ってみよう」とは思わない!


2
ここではっきりしているのはdatetimedatetime2データ型とSQLデータ型の両方がSQL Server 2008で導入されたことです。また、1日のドット以来存在していOperand type clash: date is incompatible with intdate型からも取得できます。3つのデータ型はすべて問題なく動作しdateadd(dd, 1, ...)ます。
AlwaysLearning 2017

2
これは明確ではありません。日時フィールドが含まれているSQLServer 2005データベースがあります。
ポールマッカーシー

0

はに比べて効率が良いので、DATETIME2を保存する方が良いと思います。で使用でき、日付と時刻を格納し、格納に6〜8時間がかかり、精度がです。したがって、より高い時間精度を必要とする人は誰でも欲しくなるでしょう。dateDATETIMESQL Server 2008DATETIME2bytes100 nanosecondsDATETIME2

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.