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

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

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

    どちらを使用するかわからない場合は、 datetime2を使用してください (以下の利点を参照してください。)

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

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

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

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

    「datetime2」の利点

    上記の表に示されているように、 datetime2 タイプには、日時よりも多くの利点があります 、含む:

    • より広い日付範囲
    • デフォルトの分数精度が大きい
    • オプションのユーザー指定の精度
    • datetime と同じ小数点以下の桁数を使用する場合でも、より高い精度 (つまり3)
    • datetime と同じ小数点以下の桁数を使用すると、ストレージサイズが小さくなります 、しかも精度が高い*
    • datetimeより2バイト少ないストレージを使用するオプション (精度は低くなりますが)*
    • SQL標準(ANSIおよびISO 8601)に準拠

    *場合によってはdatetime2 valueは、精度を格納するために追加のバイトを使用します。これにより、 datetimeと同じストレージサイズになります。 同じ小数点以下の桁数を使用する場合。これについてもっと知るために読んでください。

    「datetime」と「datetime2」のどちらを使用する必要がありますか?

    Microsoftはdatetime2を推奨しています 日時以上 新しい仕事のために(そして上記と同じ理由で)

    したがって、 datetime2を使用する必要があります 、特別な理由がない限り(レガシーシステムでの作業など)。

    例1-基本的な比較

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

    DECLARE 
      @thedatetime2 datetime2(7), 
      @thedatetime datetime;
    SET @thedatetime2 = '2025-05-21 10:15:30.5555555';
    SET @thedatetime = @thedatetime2;
    SELECT 
      @thedatetime2 AS 'datetime2',
      @thedatetime AS 'datetime';
    

    結果:

    +-----------------------------+-------------------------+
    | datetime2                   | datetime                |
    |-----------------------------+-------------------------|
    | 2025-05-21 10:15:30.5555555 | 2025-05-21 10:15:30.557 |
    +-----------------------------+-------------------------+
    

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

    この場合、 datetime2 変数は7のスケールを使用します。これは、小数点以下7桁を意味します。 日時 一方、値は小数点以下3桁のみを使用し、最後の小数桁は切り上げられます(このデータ型は、小数秒を.000、.003、または.007秒の増分に丸めるため)。

    例2–小数点以下3桁の使用

    datetime2を減らすと 3にスケールします( dateime に一致させるため) )、これが何が起こるかです。

    DECLARE 
      @thedatetime2 datetime2(3), 
      @thedatetime datetime;
    SET @thedatetime2 = '2025-05-21 10:15:30.5555555';
    SET @thedatetime = @thedatetime2;
    SELECT 
      @thedatetime2 AS 'datetime2',
      @thedatetime AS 'datetime';
    

    結果:

    +-------------------------+-------------------------+
    | datetime2               | datetime                |
    |-------------------------+-------------------------|
    | 2025-05-21 10:15:30.556 | 2025-05-21 10:15:30.557 |
    +-------------------------+-------------------------+
    

    つまり、 datetime2 この場合、値も切り上げられます。ただし、 556 に切り上げられるだけです。 – 557 にはジャンプしません 日時のように 値はありません。

    もちろん、 datetime2の唯一の理由は 値が切り上げられるのは、次の桁が5以上であるためです。次の桁を減らすと、丸めは実行されません。

    DECLARE 
      @thedatetime2 datetime2(3), 
      @thedatetime datetime;
    SET @thedatetime2 = '2025-05-21 10:15:30.5554444';
    SET @thedatetime = @thedatetime2;
    SELECT 
      @thedatetime2 AS 'datetime2',
      @thedatetime AS 'datetime';
    

    結果:

    +-------------------------+-------------------------+
    | datetime2               | datetime                |
    |-------------------------+-------------------------|
    | 2025-05-21 10:15:30.555 | 2025-05-21 10:15:30.557 |
    +-------------------------+-------------------------+
    

    ただし、日時 値は引き続き切り上げられます。

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

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

    ただし、同じ文字列リテラルを datetimeに割り当てようとすると datetime2に割り当てた変数 、エラーが発生します:

    DECLARE 
      @thedatetime2 datetime2(3), 
      @thedatetime datetime;
    SET @thedatetime2 = '2025-05-21 10:15:30.5554444';
    SET @thedatetime = '2025-05-21 10:15:30.5554444';
    SELECT 
      @thedatetime2 AS 'datetime2',
      @thedatetime AS 'datetime';
    

    結果:

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

    これは、日時が原因です 小数秒が3秒以下の文字列リテラルのみを受け入れます。

    したがって、この問題を克服するには、小数部分を小数点以下3桁(またはそれ以下)に減らす必要があります。

    DECLARE 
      @thedatetime2 datetime2(3), 
      @thedatetime datetime;
    SET @thedatetime2 = '2025-05-21 10:15:30.5554444';
    SET @thedatetime = '2025-05-21 10:15:30.555';
    SELECT 
      @thedatetime2 AS 'datetime2',
      @thedatetime AS 'datetime';
    

    結果:

    +-------------------------+-------------------------+
    | datetime2               | datetime                |
    |-------------------------+-------------------------|
    | 2025-05-21 10:15:30.555 | 2025-05-21 10:15:30.557 |
    +-------------------------+-------------------------+
    

    datetime2 スケール3を使用している場合でも、タイプにはこの制限はありません。

    例4–ストレージサイズ

    日時 データ型のストレージサイズは8バイトに固定されています。

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

    小数点以下3桁を使用する場合、 datetime2 使用するのはわずか7バイトです。つまり、 datetimeよりも少ないストレージスペースを使用します。 (より正確に)

    ただし、Microsoftは、 datetime2 typeは、精度を格納するために1バイト余分に使用します。したがって、この場合、8バイトを使用します。したがって、7、8、または9バイトのいずれかを使用すると言うことで、前のステートメントを修正できます。

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

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

    DECLARE 
      @thedatetime2 datetime2(3), 
      @thedatetime datetime;
    SET @thedatetime2 = '2025-05-21 10:15:30.5554444';
    SET @thedatetime = @thedatetime2;
    SELECT 
      DATALENGTH(@thedatetime2) AS 'datetime2',
      DATALENGTH(@thedatetime) AS 'datetime';
    

    結果

    +-------------+------------+
    | datetime2   | datetime   |
    |-------------+------------|
    | 7           | 8          |
    +-------------+------------+
    

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

    DECLARE 
      @thedatetime2 datetime2(3), 
      @thedatetime datetime;
    SET @thedatetime2 = '2025-05-21 10:15:30.5554444';
    SET @thedatetime = @thedatetime2;
    SELECT 
      DATALENGTH(CONVERT(VARBINARY(16),@thedatetime2)) AS 'datetime2',
      DATALENGTH(CONVERT(VARBINARY(16),@thedatetime)) AS 'datetime';
    

    結果

    +-------------+------------+
    | datetime2   | datetime   |
    |-------------+------------|
    | 8           | 8          |
    +-------------+------------+
    

    つまり、 datetime2 varbinaryに変換されるときに余分なバイトを使用します 、したがって、日時と同じストレージサイズになります 。

    ただし、次の例は、データがデータベース列に格納されている場合、 datetime2の長さが7バイトになることを示しています。 日時の場合は8バイト 。

    datetime2を保存する場合 データベース内の値の場合、列定義には精度が含まれます。この場合、各行の値は精度を格納するために余分なバイトを必要とせず、 datetime2 と言うことができます 日時よりも少ないストレージスペースを使用します 同じ小数秒数を使用する場合。

    例5–保存されたデータのストレージサイズ

    この例では、データベースを作成し、COL_LENGTHを使用します 各列の長さをバイト単位で返します。次に、 datetime2を挿入します および日時 値を入力し、DBCC PAGE()を使用します ページファイル内の実際のデータの長さを検索します。これは、各データ型がデータベースに保存されるときに使用するストレージスペースを示しています。

    データベースを作成します:

    CREATE DATABASE CompareTypes;
    

    テーブルを作成します:

    USE CompareTypes;
    
    CREATE TABLE Datetime2vsDatetime (
        TheDateTime datetime,
        TheDateTime2 datetime2(3)
        );
    

    この場合、2つの列を作成します。1つは日時です 列ともう1つはdatetime2 列。

    列の長さを確認する

    各列の長さ(バイト単位)を確認してください:

    SELECT 
      COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime2' ) AS 'datetime2',
      COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime' ) AS 'datetime';  
    

    結果:

    +-------------+------------+
    | datetime2   | datetime   |
    |-------------+------------|
    | 7           | 8          |
    +-------------+------------+
    

    したがって、 datetime2 datetime と比較して、列の長さは7バイトです。 の長さは8バイトです。

    データを挿入

    次に、SQLServerに保存された実際の日付と時刻の値のストレージサイズを見てみましょう。 DBCC PAGE()を使用できます データファイルの実際のページを検査します。

    ただし、最初に、列にデータを挿入する必要があります。

    データの挿入:

    DECLARE @thedatetime2 datetime2 = '2025-05-21 10:15:30.5554444';
    INSERT INTO Datetime2vsDatetime ( TheDateTime, TheDateTime2 )
    SELECT @thedatetime2, @thedatetime2;
    

    データを選択します(確認するためだけに):

    SELECT * FROM Datetime2vsDatetime;
    

    結果:

    +-------------------------+-------------------------+
    | TheDateTime             | TheDateTime2            |
    |-------------------------+-------------------------|
    | 2025-05-21 10:15:30.557 | 2025-05-21 10:15:30.555 |
    +-------------------------+-------------------------+
    

    DBCC PAGE()の使用

    ここでDBCC PAGE()を使用します データファイルの実際のページを検査します。

    まず、DBCC IND()を使用します PagePIDを見つけるには:

    DBCC IND('CompareTypes', 'dbo.Datetime2vsDatetime', 0);
    

    結果(垂直出力を使用):

    -[ RECORD 1 ]-------------------------
    PageFID         | 1
    PagePID         | 307
    IAMFID          | NULL
    IAMPID          | NULL
    ObjectID        | 885578193
    IndexID         | 0
    PartitionNumber | 1
    PartitionID     | 72057594042974208
    iam_chain_type  | In-row data
    PageType        | 10
    IndexLevel      | NULL
    NextPageFID     | 0
    NextPagePID     | 0
    PrevPageFID     | 0
    PrevPagePID     | 0
    -[ RECORD 2 ]-------------------------
    PageFID         | 1
    PagePID         | 320
    IAMFID          | 1
    IAMPID          | 307
    ObjectID        | 885578193
    IndexID         | 0
    PartitionNumber | 1
    PartitionID     | 72057594042974208
    iam_chain_type  | In-row data
    PageType        | 1
    IndexLevel      | 0
    NextPageFID     | 0
    NextPagePID     | 0
    PrevPageFID     | 0
    PrevPagePID     | 0
    

    これにより、2つのレコードが返されます。 PageType of 1(2番目のレコード)に関心があります。そのレコードからPagePIDが必要です。この場合、PagePIDは 320 です。 。

    これで、そのPagePIDを取得して、次の場所で使用できます。

    DBCC TRACEON(3604, -1);
    DBCC PAGE(CompareTypes, 1, 320, 3);
    

    これにより大量のデータが生成されますが、主に次の部分に関心があります。

    Slot 0 Column 1 Offset 0x4 Length 8 Length (physical) 8
    
    TheDateTime = 2025-05-21 10:15:30.557                                    
    
    Slot 0 Column 2 Offset 0xc Length 7 Length (physical) 7
    
    TheDateTime2 = 2025-05-21 10:15:30.555                                    
    

    これは、日時が 8バイトの長さとdatetime2(3)を使用します データベースに保存するときに7バイトを使用します。

    したがって、これは datetime2を使用する場合を補強します 日時以上 新しいデータベースを設計するとき、特にストレージサイズが懸念される場合。


    1. Android sqlite、データベースの行数を制限する

    2. 現在利用可能なより多くのオンライン操作–または間もなく

    3. OracleDBの引用列名

    4. SQL SUBSTRING()関数を使用してプロのように文字列を解析する方法は?