この記事では、 datetime2の主な違いについて説明します。 およびsmalldatetime SQLServerのデータ型。
両方のデータ型は日付と時刻の値を格納するために使用されますが、2つの間にいくつかの重要な違いがあります。ほとんどの場合、 datetime2を使用することをお勧めします (Microsoftもこれを推奨しています)ただし、 smalldatetimeを使用する必要があるシナリオがいくつかある場合があります。 。
これら2つのタイプの主な違いの概要を示す表を次に示します。
機能 | smalldatetime | datetime2 |
---|---|---|
SQL準拠(ANSIおよびISO 8601) | いいえ | はい |
日付範囲 | 1900-01-01から2079-06-06 | 0001-01-01から9999-12-31 |
時間範囲 | 00:00:00から23:59:59 | 00:00:00から23:59:59.9999999 |
文字の長さ | 最大19ポジション | 最小19ポジション 最大27ポジション |
ストレージサイズ | 4バイト、固定 | 精度に応じて6〜8バイト* *精度を格納するためのプラス1バイト |
精度 | 1分 | 100ナノ秒 |
フラクショナルセカンドプレシジョン | いいえ | はい |
ユーザー定義の分数秒精度 | いいえ | はい |
タイムゾーンオフセット | なし | なし |
タイムゾーンオフセットの認識と保存 | いいえ | いいえ |
夏時間対応 | いいえ | いいえ |
「datetime2」の利点
上記の表に示されているように、 datetime2 タイプには、 smalldatetimeよりも多くの利点があります 、含む:
- より広い日付範囲
- 秒の精度
- オプションのユーザー指定の精度
- より高い精度
- SQL標準(ANSIおよびISO 8601)に準拠
*場合によってはdatetime2 valueは、精度を格納するために追加のバイトを使用しますが、データベースに格納される場合、精度は列定義に含まれるため、実際に格納された値は追加のバイトを必要としません。
「datetime」と「smalldatetime」のどちらを使用する必要がありますか?
Microsoftはdatetime2を推奨しています 新しい仕事のために(そして上記と同じ理由で)
したがって、 datetime2を使用する必要があります 、特別な理由がない限り(レガシーシステムでの作業など)。
例1-基本的な比較
datetime2の基本的な違いを示す簡単な例を次に示します。 およびsmalldatetime 。
DECLARE @thedatetime2 datetime2(7), @thesmalldatetime smalldatetime; SET @thedatetime2 = '2025-05-21 10:15:30.5555555'; SET @thesmalldatetime = @thedatetime2; SELECT @thedatetime2 AS 'datetime2', @thesmalldatetime AS 'smalldatetime';
結果:
+-----------------------------+---------------------+ | datetime2 | smalldatetime | |-----------------------------+---------------------| | 2025-05-21 10:15:30.5555555 | 2025-05-21 10:16:00 | +-----------------------------+---------------------+
ここでは、 smalldatetimeを設定します datetime2と同じ値に変数 変数。これにより、値が smalldatetimeに変換されます その後、SELECT
を使用できます 各変数の値を確認するステートメント。
この場合、 datetime2 変数は7のスケールを使用します。これは、小数点以下7桁であることを意味します。 smalldatetime 一方、価値はありません 小数位。さらに、秒はゼロに設定され、分は切り上げられます。
Microsoftの公式ドキュメントには、smalldatetime
と記載されているため、これは予想されることです。 の時間は1日24時間に基づいており、秒は常にゼロ(:00)であり、小数秒はありません
。 。
したがって、 datetime2 typeは、はるかに正確で正確な日付/時刻の値を提供します。
もちろん、これらすべての秒数は必要ないかもしれません。 datetime2の良いところの1つ つまり、必要な秒数(ある場合)を指定できます。
例2–小数点以下の桁数を使用する
この例では、 datetime2を減らします 0にスケール:
DECLARE @thedatetime2 datetime2(0), @thesmalldatetime smalldatetime; SET @thedatetime2 = '2025-05-21 10:15:30.5555555'; SET @thesmalldatetime = @thedatetime2; SELECT @thedatetime2 AS 'datetime2', @thesmalldatetime AS 'smalldatetime';
結果:
+---------------------+---------------------+ | datetime2 | smalldatetime | |---------------------+---------------------| | 2025-05-21 10:15:31 | 2025-05-21 10:16:00 | +---------------------+---------------------+
この場合、 datetime2 値に小数部分が含まれなくなりました。両方のタイプが同じ文字長(19ポジション)を共有するようになりました。
しかし、まだ違いがあります。
datetime2 値は秒の値を尊重しますが、この場合、その秒は切り上げられています。前述のように、 smalldatetime 値の秒コンポーネントは常にゼロに設定されており、この場合、その分は切り上げられています。
datetime2の理由 秒の成分が切り上げられるのは、小数部が5以上であるためです。小数部分を減らすと、丸めは実行されません:
DECLARE @thedatetime2 datetime2(0), @thesmalldatetime smalldatetime; SET @thedatetime2 = '2025-05-21 10:15:30.4444444'; SET @thesmalldatetime = @thedatetime2; SELECT @thedatetime2 AS 'datetime2', @thesmalldatetime AS 'smalldatetime';
結果:
+---------------------+---------------------+ | datetime2 | smalldatetime | |---------------------+---------------------| | 2025-05-21 10:15:30 | 2025-05-21 10:16:00 | +---------------------+---------------------+
ただし、 smalldatetime 値の分は引き続き切り上げられます。
例3–文字列リテラルからの値の設定
前の例では、 smalldateime 値は、 datetime2と同じ値に設定することによって割り当てられました 価値。これを行うと、SQL Serverは、データが新しいデータ型に「適合する」ために暗黙的な変換を実行します。
ただし、同じ文字列リテラルを smalldatetimeに割り当てようとすると 変数の場合、エラーが発生します:
DECLARE @thedatetime2 datetime2(0), @thesmalldatetime smalldatetime SET @thedatetime2 = '2025-05-21 10:15:30.4444444' SET @thesmalldatetime = '2025-05-21 10:15:30.4444444' SELECT @thedatetime2 AS 'datetime2', @thesmalldatetime AS 'smalldatetime';
結果:
Msg 295, Level 16, State 3, Line 5 Conversion failed when converting character string to smalldatetime data type.
これは、 smalldatetime 小数秒が3秒以下の文字列リテラルのみを受け入れます。
anyの文字列リテラルは受け入れられないと思われるかもしれません。 分数秒は含まれていませんが、そうではありません。幸いにも3秒を受け入れますが、それ以上は受け入れません。
したがって、この問題を克服するには、小数部分を小数点以下3桁(またはそれ以下)に減らす必要があります。
DECLARE @thedatetime2 datetime2(0), @thesmalldatetime smalldatetime; SET @thedatetime2 = '2025-05-21 10:15:30.4444444'; SET @thesmalldatetime = '2025-05-21 10:15:30.444'; SELECT @thedatetime2 AS 'datetime2', @thesmalldatetime AS 'smalldatetime';
結果:
+---------------------+---------------------+ | datetime2 | smalldatetime | |---------------------+---------------------| | 2025-05-21 10:15:30 | 2025-05-21 10:16:00 | +---------------------+---------------------+
datetime2 スケール0を使用している場合でも、タイプにはこの制限はありません。
例4–ストレージサイズ
smalldatetime データ型のストレージサイズは4バイトに固定されています。これは、 smalldatetimeの数少ないメリットの1つです。 datetime2を超えています 。
datetime2 精度に応じて、6、7、または8バイトのいずれかになります。つまり、 datetime2 値は常にsmalldatetimeよりも少なくとも2バイト多くのストレージを使用します 値。
Microsoftは、 datetime2 typeは、精度を格納するために1バイト余分に使用します。この場合、 smalldatetimeより少なくとも3バイト多く使用します。 。
ただし、これはおそらく、テーブルに格納するか変数に格納するか、およびバイナリ定数に変換するかどうかによって異なります。
DATALENGTH()
を使用するとどうなりますか 各値に使用されたバイト数を返す関数:
DECLARE @thedatetime2 datetime2(0), @thesmalldatetime smalldatetime; SET @thedatetime2 = '2025-05-21 10:15:30'; SET @thesmalldatetime = @thedatetime2; SELECT DATALENGTH(@thedatetime2) AS 'datetime2', DATALENGTH(@thesmalldatetime) AS 'smalldatetime';
結果
+-------------+-----------------+ | datetime2 | smalldatetime | |-------------+-----------------| | 6 | 4 | +-------------+-----------------+
しかし、それらを varbinaryに変換すると 、次のようになります:
DECLARE @thedatetime2 datetime2(0), @thesmalldatetime smalldatetime; SET @thedatetime2 = '2025-05-21 10:15:30'; SET @thesmalldatetime = @thedatetime2; SELECT DATALENGTH(CAST(@thedatetime2 AS varbinary(10))) AS 'datetime2', DATALENGTH(CAST(@thesmalldatetime AS varbinary(10))) AS 'smalldatetime';
結果
+-------------+-----------------+ | datetime2 | smalldatetime | |-------------+-----------------| | 7 | 4 | +-------------+-----------------+
つまり、 datetime2 varbinaryに変換されるときに余分なバイトを使用します 。多くの開発者は、 varbinaryへの変換を想定しています SQLServerが実際に日付と時刻の値を格納する方法を表しています。
ただし、これは部分的にしか当てはまりません。 SQL Serverが日付と時刻の値を16進数で格納しているのは事実ですが、その16進値には実際には精度が含まれていません。これは、精度が列定義に含まれているためです。しかし、 varbinaryに変換すると 前の例で行ったように、精度が付加され、これにより余分なバイトが追加されます。
次の例はこれを示しています。これは、データがデータベース列に格納されている場合、 datetime2の長さが6バイトになることを示しています。 vs smalldatetimeの場合は4バイト 。
例5–保存されたデータのストレージサイズ
この例では、データベースを作成し、COL_LENGTH
を使用します 各列の長さをバイト単位で返します。次に、 datetime2を挿入します およびsmalldatetime 値を入力し、DBCC PAGE()
を使用します ページファイル内の実際のデータの長さを検索します。これは、各データ型がデータベースに保存されるときに使用するストレージスペースを示しています。
データベースを作成します:
CREATE DATABASE CompareTypes;
テーブルを作成します:
USE CompareTypes; CREATE TABLE Datetime2vsSmalldatetime ( TheDateTime2 datetime2(0), TheSmallDateTime smalldatetime );
この場合、2つの列を作成します。1つは datetime2(0)です。 列ともう1つはsmalldatetime 列。
列の長さを確認する
各列の長さ(バイト単位)を確認してください:
SELECT COL_LENGTH ( 'dbo.Datetime2vsSmalldatetime' , 'TheDateTime2' ) AS 'datetime2', COL_LENGTH ( 'dbo.Datetime2vsSmalldatetime' , 'TheSmallDateTime' ) AS 'smalldatetime';
結果:
+-------------+-----------------+ | datetime2 | smalldatetime | |-------------+-----------------| | 6 | 4 | +-------------+-----------------+
したがって、 datetime2(0) smalldatetime と比較して、列の長さは6バイトです。 の長さは4バイトです。
データを挿入
次に、SQLServerに保存された実際の日付と時刻の値のストレージサイズを見てみましょう。 DBCC PAGE()
を使用できます データファイルの実際のページを検査します。
ただし、最初に、列にデータを挿入する必要があります。
データの挿入:
DECLARE @thedatetime2 datetime2 = '2025-05-21 10:15:30'; INSERT INTO Datetime2vsSmalldatetime ( TheSmallDateTime, TheDateTime2 ) SELECT @thedatetime2, @thedatetime2;
データを選択します(確認するためだけに):
SELECT * FROM Datetime2vsSmalldatetime;
結果:
+---------------------+---------------------+ | TheDateTime2 | TheSmallDateTime | |---------------------+---------------------| | 2025-05-21 10:15:30 | 2025-05-21 10:16:00 | +---------------------+---------------------+
DBCC PAGE()の使用
ここでDBCC PAGE()
を使用します データファイルの実際のページを検査します。
まず、DBCC IND()
を使用します PagePIDを見つけるには:
DBCC IND('CompareTypes', 'dbo.Datetime2vsSmalldatetime', 0);
結果(垂直出力を使用):
-[ RECORD 1 ]------------------------- PageFID | 1 PagePID | 308 IAMFID | NULL IAMPID | NULL ObjectID | 1205579333 IndexID | 0 PartitionNumber | 1 PartitionID | 72057594043039744 iam_chain_type | In-row data PageType | 10 IndexLevel | NULL NextPageFID | 0 NextPagePID | 0 PrevPageFID | 0 PrevPagePID | 0 -[ RECORD 2 ]------------------------- PageFID | 1 PagePID | 344 IAMFID | 1 IAMPID | 308 ObjectID | 1205579333 IndexID | 0 PartitionNumber | 1 PartitionID | 72057594043039744 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は 344 です。 。
これで、そのPagePIDを取得して、次の場所で使用できます。
DBCC TRACEON(3604, -1); DBCC PAGE(CompareTypes, 1, 344, 3);
これにより大量のデータが生成されますが、主に次の部分に関心があります。
Slot 0 Column 1 Offset 0x4 Length 6 Length (physical) 6 TheDateTime2 = 2025-05-21 10:15:30 Slot 0 Column 2 Offset 0xa Length 4 Length (physical) 4 TheSmallDateTime = 2025-05-21 10:16:00.000
これは、 smalldatetime 長さは4バイトで、 datetime2(0) データベースに保存すると6バイトになります。
したがって、この場合、2バイトの違いしかありませんが、 datetime2(0) より正確で、ANSIおよびISO8601規格に準拠しています。