sql >> データベース >  >> RDS >> Sqlserver

SQL Serverでのdatetimeとdatetimeoffsetの違い:違いは何ですか?

    この記事では、日時の主な違いについて説明します。 およびdatetimeoffset SQLServerのデータ型。

    両方のデータ型は、日付と時刻の値を格納するために使用されます。しかし、この2つには大きな違いがあります。

    おそらく最も明らかな違いは、 datetimeoffset datetime に対して、タイムゾーンオフセットを格納します しません。

    もう1つの重要な違いは、 datetimeoffset 精度を指定できます(小数点以下7桁まで)。これは、 datetimeoffset を意味します 値は、使用されている精度に応じて、ストレージサイズが異なる場合があります。

    日時 一方、タイプは、固定のストレージサイズと精度を備えています。

    通常、 datetimeの使用は避けてください。 使用する正当な理由がない限り(レガシーシステムのサポートなど)。また、 datetime2 タイプはdatetimeoffsetよりも厳密に一致します 、したがって、タイムゾーンオフセットが必要ない場合は、これを使用することをお勧めします。

    いずれにせよ、これが日時を比較した表です およびdatetimeoffset

    機能 datetimeoffset 日時
    SQL準拠(ANSIおよびISO 8601) はい いいえ
    日付範囲 0001-01-01から9999-12-31 1753-01-01から9999-12-31
    時間範囲 00:00:00から23:59:59.9999999 00:00:00から23:59:59.997
    文字の長さ 最小26ポジション
    最大34ポジション
    最小19ポジション
    最大23ポジション
    ストレージサイズ 精度に応じて8〜10バイト*

    *場合によっては精度を格納するためのプラス1バイト。詳細については、以下を参照してください。

    8バイト
    精度 100ナノ秒 .000、.003、または.007秒の増分に丸められます
    ユーザー定義の分数秒精度 はい いいえ
    タイムゾーンオフセット範囲 -14:00〜+ 14:00 なし
    タイムゾーンオフセットの認識と保存 はい いいえ
    夏時間対応 いいえ いいえ

    例1-基本的な比較

    いずれにせよ、日時の基本的な違いを示す簡単な例を次に示します。 およびdatetimeoffset

    DECLARE 
      @thedatetimeoffset datetimeoffset(7), 
      @thedatetime datetime;
    SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30';
    SET @thedatetime = @thedatetimeoffset;
    SELECT 
      @thedatetimeoffset AS 'datetimeoffset',
      @thedatetime AS 'datetime';
    

    結果:

    +------------------------------------+-------------------------+
    | datetimeoffset                     | datetime                |
    |------------------------------------+-------------------------|
    | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.557 |
    +------------------------------------+-------------------------+
    

    ここでは、日時を設定します datetimeoffsetと同じ値に変数 変数。これにより、値が datetimeに変換されます その後、SELECTを使用できます 各変数の値を確認するステートメント。

    この場合、 datetimeoffset 値には、タイムゾーンオフセットと小数点以下7桁が含まれます。 日時 一方、値にはタイムゾーンオフセットは含まれず、小数点以下3桁しかありません。さらに、その3番目の小数桁は切り上げられます。これは、その精度が常に.000、.003、または.007秒の増分に丸められるためです。

    例2–文字列リテラルからの値の設定

    前の例では、日時 値は、 datetimeoffsetと同じ値に設定することによって割り当てられました 価値。これを行うと、SQL Serverは、データが新しいデータ型に「適合する」ために暗黙的な変換を実行します。

    同じ値を日時に直接割り当てようとした場合 エラーが発生する変数:

    DECLARE 
      @thedatetimeoffset datetimeoffset(7), 
      @thedatetime datetime;
    SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30';
    SET @thedatetime = '2025-05-21 10:15:30.5555555 +07:30';
    SELECT 
      @thedatetimeoffset AS 'datetimeoffset',
      @thedatetime AS 'datetime';
    

    結果:

    Msg 241, Level 16, State 1, Line 5
    Conversion failed when converting date and/or time from character string.
    

    これは、日時が原因です データ型は、タイムゾーンオフセットのある文字列リテラルをサポートしていません。また、小数点以下3桁を超える文字列リテラルはサポートされていません。

    したがって、タイムゾーンオフセットを削除しても、すべての小数秒を保持すると、エラーが発生します:

    DECLARE 
      @thedatetimeoffset datetimeoffset(7), 
      @thedatetime datetime;
    SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30';
    SET @thedatetime = '2025-05-21 10:15:30.5555555';
    SELECT 
      @thedatetimeoffset AS 'datetimeoffset',
      @thedatetime AS 'datetime';
    

    結果:

    Msg 241, Level 16, State 1, Line 5
    Conversion failed when converting date and/or time from character string.
    

    それを機能させるには、小数点以下3桁以下の値を割り当てる必要があります:

    DECLARE 
      @thedatetimeoffset datetimeoffset(7), 
      @thedatetime datetime;
    SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30';
    SET @thedatetime = '2025-05-21 10:15:30.555';
    SELECT 
      @thedatetimeoffset AS 'datetimeoffset',
      @thedatetime AS 'datetime';
    

    結果:

    +------------------------------------+-------------------------+
    | datetimeoffset                     | datetime                |
    |------------------------------------+-------------------------|
    | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.557 |
    +------------------------------------+-------------------------+
    

    いずれにせよ、日時 datetimeoffsetとは常に異なる値を保持します 、タイムゾーンオフセットが含まれていないためです。これは、同じ小数秒の精度と小数秒の値を使用する場合でも当てはまります。

    これを示すために、 datetimeoffsetに同じ値を割り当てるとどうなりますか。 :

    DECLARE 
      @thedatetimeoffset datetimeoffset(3), 
      @thedatetime datetime;
    SET @thedatetimeoffset = '2025-05-21 10:15:30.123';
    SET @thedatetime = '2025-05-21 10:15:30.123';
    SELECT 
      @thedatetimeoffset AS 'datetimeoffset',
      @thedatetime AS 'datetime';
    

    結果:

    +------------------------------------+-------------------------+
    | datetimeoffset                     | datetime                |
    |------------------------------------+-------------------------|
    | 2025-05-21 10:15:30.1230000 +00:00 | 2025-05-21 10:15:30.123 |
    +------------------------------------+-------------------------+
    

    この場合、 datetimeoffset スケール3を使用し、小数点以下3桁になります(日時と同じ) )。これは、 datetimeoffset(3)を使用して行われます。 変数を宣言するとき。

    また、日時になるように小数秒を変更しました それらを切り上げません(両方の値がまったく同じ小数部分を共有するように)。

    とにかく、 datetimeoffset それでもタイムゾーンオフセットを追加し、デフォルト値の+00:00に設定します。

    私のシステムはdatetimeoffsetに末尾のゼロを表示することに注意してください の小数部ですが、値は小数点以下3桁のみを使用します。

    例3–ストレージサイズ

    日時 データ型は8バイトを使用します。

    datetimeoffset データ型は、その精度に応じて、8、9、または10バイトのいずれかを使用します。

    したがって、 datetimeを使用してストレージサイズを節約することはありません。 。

    ただし、 datetimeoffsetを変換する場合 バイナリ定数に値を追加すると、精度を格納するために1バイトが追加されます。

    DATALENGTH()を使用するとどうなりますか 各値に使用されたバイト数を返す関数:

    DECLARE 
      @thedatetimeoffset datetimeoffset(7), 
      @thedatetime datetime;
    SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30';
    SET @thedatetime = @thedatetimeoffset;
    SELECT 
      DATALENGTH(@thedatetimeoffset) AS 'datetimeoffset',
      DATALENGTH(@thedatetime) AS 'datetime';
    

    結果

    +------------------+------------+
    | datetimeoffset   | datetime   |
    |------------------+------------|
    | 10               | 8          |
    +------------------+------------+
    

    予想どおり、 datetimeoffsetの場合は10バイト 日時の場合は8バイト 。

    しかし、それらを varbinaryに変換すると 、次のようになります:

    DECLARE 
      @thedatetimeoffset datetimeoffset(7), 
      @thedatetime datetime;
    SET @thedatetimeoffset = '2025-05-21 10:15:30.5555555 +07:30';
    SET @thedatetime = @thedatetimeoffset;
    SELECT 
      DATALENGTH(CAST(@thedatetimeoffset AS varbinary(16))) AS 'datetimeoffset',
      DATALENGTH(CAST(@thedatetime AS varbinary(16))) AS 'datetime';
    

    結果

    +------------------+------------+
    | datetimeoffset   | datetime   |
    |------------------+------------|
    | 11               | 8          |
    +------------------+------------+
    

    datetimeoffsetに1バイトが追加されます 値ですが、日時にはなりません 価値。これは、 datetimeoffsetが原因です。 値には、精度を格納するために追加のバイトが必要です(精度はユーザー定義であるため)。 日時 一方、値の精度は固定されているため、値とともに精度を保存する必要はありません。

    多くの開発者は、 varbinaryへの変換を想定しています SQLServerが実際に日付と時刻の値を格納する方法を表しています。ただし、これは部分的にしか当てはまりません。

    SQL Serverが日付と時刻の値を16進数で格納することは事実ですが、その16進値には、 datetimeoffsetを格納するときの精度は実際には含まれていません。 値。これは、精度が列定義に含まれているためです。

    このデータ型がデータベースに格納される方法の詳細については、SQLServerの「datetimeoffset」ストレージサイズについてを参照してください。

    「datetime」または「datetimeoffset」を使用する必要がありますか?

    タイムゾーンオフセットを含める必要がある場合は、 datetimeoffsetを使用する必要があります 。そうでない場合は、日時 十分かもしれません。

    ただし、Microsoftでは datetime2を使用することをお勧めします 日時よりも多くのメリットがあるため、新しい作業の場合 。

    これらのデータ型の比較については、datetimeとdatetime2を参照してください。


    1. エンティティフレームワークを使用して主キー値を更新します

    2. psycopg2 TypeErrorの処理方法:文字列のフォーマット中にすべての引数が変換されるわけではありません

    3. おそらくあなたが知らないマイクロソフトについての6つのおもしろ情報!

    4. Debian 5でMySQLリレーショナルデータベースを使用する(Lenny)