834

どれ:

SQL Server 2008+で日付と時刻を保存するための推奨される方法は何ですか?

精度(およびおそらくストレージスペース)の違いを認識していますが、今のところそれらを無視して、いつ何を使用するかについてのベストプラクティスドキュメントがありますか、それとも単に使用する必要がありますdatetime2か?

4

16 に答える 16

709

datetimeのMSDNドキュメントでは、datetime2の使用を推奨しています。ここに彼らの推薦があります:

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

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

于 2009-12-10T21:17:57.087 に答える
548

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

また、必要に応じて、DATETIME2時間の観点からより正確にすることができます。DATETIMEは31/3ミリ秒に制限されていますが、 DATETIME2100nsまで正確にすることができます。

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

選択肢があれば、DATETIME2可能な限り使用することをお勧めします。DATETIME(下位互換性を除いて)使用する利点は見当たりません-問題が少なくなります(日付が範囲外であり、そのような面倒な作業があります)。

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

于 2009-08-26T11:56:52.297 に答える
234

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

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

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

以下の点にご注意ください

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

イメージソース: MCTSセルフペーストレーニングキット(試験70-432):Microsoft®SQLServer®2008-実装と保守 第3章:テーブル->レッスン1:テーブルの作成->66ページ

于 2012-09-11T06:52:33.820 に答える
113

私は@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ます。.netDatetimeを古いSQLにマッピングするとDateTime暗黙的な丸めが発生します。古いSQLDateTimeは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に移行する重要な理由です。日付の暗黙的な丸めは明らかに混乱を引き起こします:

于 2012-03-08T18:00:51.077 に答える
27

ほとんどすべての回答とコメントは、長所に重く、短所に軽いものでした。これは、これまでのすべての長所と短所に加えて、いくつかの重要な短所(以下の#2)の要約です。

  1. 長所:

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

1.2。より多くの範囲(1/1/0001から12/31/9999対1/1/1753-12/31/9999)(ただし、1753年より前の追加の範囲は、例を除いて使用されない可能性があります。歴史的、天文学的、地質学的などのアプリで)。

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

1.4。より高い精度(100ナノ秒別名0.000,000,1秒vs. 3.33ミリ秒別名0.003,33秒)(ただし、エンジニアリング/科学アプリなどを除いて、追加の精度は使用されない可能性があります)。

1.5。同様の(Iman Abidiが主張したように「同じ」ではない(3.33ミリ秒のように)1ミリ秒のように)精度を設定するとDateTime、使用するスペースは少なくなります(7バイトと8バイト)が、もちろん、精度のメリットは、おそらく不要なメリットではありますが、2つのうちの1つ(もう1つは範囲)で最も宣伝されています)。

  1. 短所:

2.1。パラメータを.NETに渡すときは、SQL Serverの範囲や精度の範囲外の値を渡す可能性があるかどうかをSqlCommand指定する必要があります。これは、デフォルトで.NETになっているためです。System.Data.SqlDbType.DateTime2DateTimeSystem.Data.SqlDbType.DateTime

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

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

2.2.2。「年齢」の計算のために、2つの日時の差を取ります。注:SQL ServerのDateDiff関数を代わりに使用することはできません。これはage、2つの日時が、ごくわずかであっても、指定された単位のカレンダー/時計の日時の境界を超えた場合に、ほとんどの人が期待するように計算されないためです。その単位の差は、その単位の1対0として返されます。たとえば、わずか1ミリ秒離れた2つの日時のDateDiffinは、それらの日時が次の場合、1対0(日)を返します。Day異なる暦日(つまり、「1999-12-31 23:59:59.9999999」および「2000-01-0100:00:00.0000000」)。同じ1ミリ秒の差の日時は、暦日を超えないように移動した場合Day、0(日)の'sで「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」</ p>

もちろん、最初に(そして必要に応じて再びに戻る)Castすることもできますが、対の精度と範囲(すべて1753年より前)の利点が失われます。足し算/引き算/「年齢」(対)/大きなものである計算の利点のために浮動小数点数値(日数)への暗黙的/簡単な変換を失うときになぜそれを使用するのかという疑問を投げかける最も必要性の低い2つ私の経験では。DateTimeDateTime2DateTime2DateTimeDateDiffAvg

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

于 2017-07-10T19:00:32.237 に答える
16

以下は、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バイト節約できます。

于 2015-09-11T17:29:53.293 に答える
15

DateTime2 wreaks havoc if you are an Access developer trying to write Now() to the field in question. Just did an Access -> SQL 2008 R2 migration and it put all the datetime fields in as DateTime2. Appending a record with Now() as the value bombed out. It was okay on 1/1/2012 2:53:04 PM, but not on 1/10/2012 2:53:04 PM.

Once character made the difference. Hope it helps somebody.

于 2012-02-13T19:52:43.347 に答える
11

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

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秒もかかりません。

乾杯

于 2018-02-09T05:08:27.687 に答える
10

米国以外の設定を使用する場合、日付文字列の解釈も異なる場合がdatetimeあります。例えばdatetime2DATEFORMAT

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日)、。に対して(つまり、6datetime月5日)を返します。ただし、に設定すると、両方とが返されます。2013-06-05datetime2dateformatmdy@d@d22013-06-05

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

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

于 2013-06-21T13:11:19.763 に答える
10

datetime2を使用すると精度が向上しますが、一部のクライアントはdatetime、またはdatetime2をサポートしておらず、文字列リテラルに変換する必要があります。具体的には、Microsoftは、これらのデータ型に関する「ダウンレベル」のODBC、OLE DB、JDBC、およびSqlClientの問題に言及し、それぞれが型をマップする方法を示す グラフを用意しています。

精度よりも互換性を重視する場合は、日時を使用してください

于 2014-06-25T20:56:15.143 に答える
6

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

于 2014-08-18T17:48:04.597 に答える
4

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

于 2017-11-04T15:31:26.223 に答える
1

他の回答が示すように、datetime2サイズが小さく精度が高いため推奨されますが、NikolaIlicのdatetime2を使用しない理由についていくつか考えます。

  • 次のような日付を使用して基本的な数学演算を実行する(単純な)可能性の欠如GETDATE()+1
  • DATEADDまたはとの比較を行うたびにDATEDIFF、暗黙のデータ変換を終了します。datetime
  • SQL Serverは、データの格納方法が最適でないクエリプランにつながり、パフォーマンスが低下するため、Datetime2列の統計を適切に使用できません。
于 2021-06-22T10:14:01.347 に答える
0

DATETIME2を保存する方dateが効率が良いので、より良い方法だと思いますDATETIMESQL Server 2008を使用できる場合DATETIME2、日付と時刻を格納し、格納に6〜8かかり、bytes精度は100 nanoseconds。です。したがって、より高い時間精度が必要な人は誰でも欲しいでしょうDATETIME2

于 2013-11-20T09:06:54.133 に答える
-1

受け入れられた答えは素晴らしいです。フロントエンドにDateTime2を送信している場合は、通常のDateTimeに相当する値に丸められることを知っておいてください。

私のソリューションでは、送信されたものと再送信されたときにデータベースにあるものを比較する必要があり、単純な比較'=='では丸めができなかったため、これは私にとって問題を引き起こしました。したがって、追加する必要がありました。

于 2021-01-11T16:27:08.397 に答える
-2
Select ValidUntil + 1
from Documents

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

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

「古いタイプよりも悪いこの新しいタイプを使いましょう」、私はそうは思いません!

于 2017-05-25T09:17:38.337 に答える