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

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

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

    両方のデータ型は、日付と時刻の値を格納するために使用されます。どちらも非常に似ていますが、重要な違いが1つあります。 datetimeoffset タイムゾーンオフセットを格納します。

    これにより、 datetimeoffsetも発生します datetime2よりも多くのストレージスペースを使用している 、したがって、 datetimeoffsetのみを使用します タイムゾーンオフセットが必要な場合。

    これら2つのタイプの主な違いの概要を示す表を次に示します。

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

    *精度を格納するためのプラス1バイト

    精度に応じて6〜8バイト*

    *精度を格納するためのプラス1バイト

    精度 100ナノ秒 100ナノ秒
    フラクショナルセカンドプレシジョン はい はい
    ユーザー定義の分数秒精度 はい はい
    タイムゾーンオフセット範囲 -14:00〜+ 14:00 なし
    タイムゾーンオフセットの認識と保存 はい いいえ
    夏時間対応 いいえ いいえ

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

    これは、タイムゾーンオフセットを含める必要があるかどうかによって異なります。

    タイムゾーンオフセットを含める必要がある場合は、 datetimeoffsetを使用する必要があります 。

    そうでない場合は、 datetime2を使用します 、ストレージスペースを節約し、データに(潜在的に間違った)タイムゾーンオフセットがあることによる潜在的な問題を排除します。

    例1-基本的な比較

    datetime2の基本的な違いを示す簡単な例を次に示します。 およびdatetimeoffset

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

    結果:

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

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

    両方の変数は7のスケールを使用します。これは、小数点以下7桁であることを意味します。

    したがって、この場合、2つの違いは、 datetimeoffsetだけです。 値には、タイムゾーンオフセットと datetime2が含まれます 価値はありません。

    例2–精度の変更

    どちらのタイプでも、精度を指定できます(0〜7のスケールを使用)。したがって、 datetime2を設定することができます datetimeoffsetよりも低い精度の値 値(およびその逆)。

    例:

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

    結果:

    +------------------------------------+-------------------------+
    | datetimeoffset                     | datetime2               |
    |------------------------------------+-------------------------|
    | 2025-05-21 10:15:30.5555555 +07:30 | 2025-05-21 10:15:30.556 |
    +------------------------------------+-------------------------+
    

    ここでdatetime2を設定します 値を3のスケールに設定します。これは、7ではなく小数点以下3桁になることを意味します。この場合、その小数秒は切り上げられます(次の小数桁が5以上であるため)。

    したがって、 datetime2 に割り当てる秒の小数部に応じて、異なる日付/時刻値を取得できることがわかります。 。これは逆の場合にも機能します(たとえば、 datetime2(7)から変換する場合 datetimeoffset(3)

    ただし、小数部分を減らすと、丸めは実行されません。

    DECLARE 
      @thedatetimeoffset datetimeoffset(7), 
      @thedatetime2 datetime2(3);
    SET @thedatetimeoffset = '2025-05-21 10:15:30.5554444 +07:30';
    SET @thedatetime2 = @thedatetimeoffset;
    SELECT 
      @thedatetimeoffset AS 'datetimeoffset',
      @thedatetime2 AS 'datetime2';
    

    結果:

    +------------------------------------+-------------------------+
    | datetimeoffset                     | datetime2               |
    |------------------------------------+-------------------------|
    | 2025-05-21 10:15:30.5554444 +07:30 | 2025-05-21 10:15:30.555 |
    +------------------------------------+-------------------------+
    

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

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

    同じ値をdatetime2に直接割り当てることもできます 変数(公式ドキュメントには、タイムゾーンオフセットのある文字列リテラルを受け入れると明示的に記載されていませんが):

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

    結果:

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

    例4–ストレージサイズ

    datetime2 データ型は、 datetimeoffsetより2バイト少ないストレージを使用します 任意の精度で。

    datetime2 精度に応じて、6、7、または8バイトのいずれかになります。

    datetimeoffset 精度に応じて、8、9、または10バイトのいずれかになります。

    Microsoftは、 datetime2 typeは、精度を格納するために1バイト余分に使用します。この場合、 smalldatetimeより少なくとも3バイト多く使用します。 。

    これはdatetimeoffsetにも適用されます (Microsoftのドキュメントには明示的に記載されていませんが)。

    ただし、これは、テーブルに格納するか変数に格納するか、およびバイナリ定数に変換するかどうかによって異なります。

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

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

    結果

    +------------------+-------------+
    | datetimeoffset   | datetime2   |
    |------------------+-------------|
    | 10               | 8           |
    +------------------+-------------+
    

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

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

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

    結果

    +------------------+-------------+
    | datetimeoffset   | datetime2   |
    |------------------+-------------|
    | 11               | 9           |
    +------------------+-------------+
    

    精度を保存するために、各値に1バイトが追加されます。

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

    SQL Serverが日付と時刻の値を16進数で格納しているのは事実ですが、その16進値には実際には精度が含まれていません。これは、精度が列定義に含まれているためです。しかし、 varbinaryに変換すると 前の例で行ったように、精度が付加され、これにより余分なバイトが追加されます。

    これらのデータ型がさまざまなコンテキストでどのように格納されるかについての詳細は、次の記事を参照してください。

    • SQLServerの「datetimeoffset」ストレージサイズを理解する
    • SQLServerの「datetime2」ストレージサイズを理解する

    1. DATETIME列のランダム値

    2. MySQLデータベースがクラッシュしたのはなぜですか?新しいMySQLフリーズフレームで洞察を得る

    3. PostgreSQL-データベースユーザー「postgres」としてのbashスクリプトからのクエリ

    4. EF5:ファイル「{0}」をデータベース「{1}」として添付できません