Cet article explore les principales différences entre le datetime et datetime2 types de données dans SQL Server.
Si vous ne savez pas lequel utiliser, utilisez datetime2 (voir ses avantages ci-dessous).
Voici un tableau qui décrit les principales différences entre ces deux types.
Fonctionnalité | dateheure | datetime2 |
---|---|---|
Conformité SQL (ANSI et ISO 8601) | Non | Oui |
Plage de dates | 1753-01-01 à 9999-12-31 | 0001-01-01 à 9999-12-31 |
Plage de temps | 00:00:00 à 23:59:59.997 | 00:00:00 à 23:59:59.9999999 |
Longueur des caractères | 19 postes minimum 23 maximum | 19 postes minimum 27 maximum |
Taille de stockage | 8 octets | 6 à 8 octets, selon la précision* * Plus 1 octet pour stocker la précision |
Précision | Arrondi à des incréments de .000, .003 ou .007 secondes | 100 nanosecondes |
Précision fractionnaire de seconde définie par l'utilisateur | Non | Oui |
Décalage du fuseau horaire | Aucun | Aucun |
Conscience et préservation du décalage horaire | Non | Non |
Respect de l'heure d'été | Non | Non |
Avantages de "datetime2"
Comme indiqué dans le tableau ci-dessus, le datetime2 type présente de nombreux avantages par rapport à datetime , y compris :
- plage de dates plus large
- plus grande précision fractionnaire par défaut
- précision facultative spécifiée par l'utilisateur
- précision supérieure, même en utilisant le même nombre de décimales que datetime (c'est-à-dire 3)
- moins de taille de stockage lors de l'utilisation du même nombre de décimales que datetime , mais avec une plus grande précision*
- l'option d'utiliser 2 octets de stockage en moins que datetime (bien qu'avec une précision moindre)*
- conforme aux normes SQL (ANSI et ISO 8601)
* Dans certains cas, un datetime2 value utilise un octet supplémentaire pour stocker la précision, ce qui donnerait la même taille de stockage que datetime en utilisant le même nombre de décimales. Lisez la suite pour en savoir plus à ce sujet.
Dois-je utiliser "datetime" ou "datetime2" ?
Microsoft recommande datetime2 sur datetime pour un nouveau travail (et pour les mêmes raisons énumérées ci-dessus).
Par conséquent, vous devez utiliser datetime2 , sauf si vous avez une raison spécifique de ne pas le faire (par exemple, si vous travaillez avec un ancien système).
Exemple 1 - Comparaison de base
Voici un exemple rapide pour démontrer la différence fondamentale entre datetime et 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';
Résultat :
+-----------------------------+-------------------------+ | datetime2 | datetime | |-----------------------------+-------------------------| | 2025-05-21 10:15:30.5555555 | 2025-05-21 10:15:30.557 | +-----------------------------+-------------------------+
Ici, j'ai défini un datetime variable à la même valeur que datetime2 variable. Cela entraîne la conversion de la valeur en datetime et nous pouvons alors utiliser un SELECT
déclaration pour voir le résultat.
Dans ce cas, la datetime2 variable utilise une échelle de 7, ce qui signifie 7 décimales. La dateheure d'autre part, utilise seulement 3 décimales et son dernier chiffre fractionnaire est arrondi (car ce type de données arrondit les fractions de seconde à des incréments de 0,000, 003 ou 007 secondes).
Exemple 2 - Utilisation de 3 décimales
Si je réduis le datetime2 échelle à 3 (pour correspondre à dateime ), voici ce qui se passe.
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';
Résultat :
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.556 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
Ainsi, le datetime2 la valeur est également arrondie dans ce cas. Cependant, il n'est arrondi qu'à 556 – il ne saute pas à 557 comme le datetime la valeur le fait.
Bien sûr, la seule raison pour laquelle le datetime2 la valeur est arrondie parce que le chiffre suivant est supérieur ou égal à 5. Si nous réduisons le chiffre suivant, aucun arrondi n'est effectué :
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';
Résultat :
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.555 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
Cependant, la datetime la valeur continue d'être arrondie.
Exemple 3 - Définition de valeurs à partir de littéraux de chaîne
Dans les exemples précédents, la dateime la valeur a été attribuée en la définissant sur la même valeur que datetime2 valeur. Lorsque nous faisons cela, SQL Server effectue une conversion implicite afin que les données « correspondent » au nouveau type de données.
Cependant, si nous essayons d'attribuer le même littéral de chaîne à la datetime variable que nous avons assignée à datetime2 , nous obtenons une erreur :
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';
Résultat :
Msg 241, Level 16, State 1, Line 5 Conversion failed when converting date and/or time from character string.
C'est parce que datetime accepte uniquement les littéraux de chaîne qui ont 3 fractions de seconde ou moins.
Donc, pour surmonter ce problème, nous devons réduire la partie fractionnaire à seulement 3 décimales (ou moins).
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';
Résultat :
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.555 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
Le datetime2 le type n'a pas cette limitation, même en utilisant une échelle de 3.
Exemple 4 - Taille de stockage
La dateheure Le type de données a une taille de stockage fixe de 8 octets.
Le datetime2 d'autre part, peut être de 6, 7 ou 8 octets, selon sa précision.
Lorsque vous utilisez 3 décimales, datetime2 utilise seulement 7 octets, ce qui signifie qu'il utilise moins d'espace de stockage que datetime (avec plus de précision).
Cependant, Microsoft indique que le datetime2 type utilise également 1 octet supplémentaire pour stocker sa précision. Donc, dans ce cas, il utiliserait 8 octets. Et on peut donc réviser l'instruction précédente en disant qu'elle utilise soit 7, 8 ou 9 octets.
Cependant, cela dépend probablement si nous le stockons dans une table ou dans une variable, et si nous le convertissons ou non en une constante binaire.
Voici ce qui se passe si nous utilisons le DATALENGTH()
fonction pour retourner le nombre d'octets utilisés pour chacune de nos valeurs :
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';
Résultat
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 7 | 8 | +-------------+------------+
Mais si nous les convertissons en varbinary , nous obtenons ceci :
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';
Résultat
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 8 | 8 | +-------------+------------+
Donc datetime2 utilise un octet supplémentaire lors de la conversion en varbinary , l'amenant ainsi à la même taille de stockage que datetime .
Cependant, l'exemple suivant montre que lorsque les données sont stockées dans une colonne de base de données, nous obtenons une longueur de 7 octets pour datetime2 et 8 octets pour datetime .
Lors du stockage de datetime2 valeurs dans une base de données, la définition de colonne inclut la précision. Dans ce cas, les valeurs de chaque ligne n'ont pas besoin de l'octet supplémentaire pour stocker la précision, et nous pouvons dire que datetime2 utilise moins d'espace de stockage que datetime lors de l'utilisation du même nombre de secondes fractionnaires.
Exemple 5 - Taille de stockage pour les données stockées
Dans cet exemple, je crée une base de données et j'utilise COL_LENGTH
pour renvoyer la longueur de chaque colonne, en octets. J'insère ensuite un datetime2 et dateheure valeur et utilisez DBCC PAGE()
pour trouver la longueur des données réelles dans le fichier d'échange. Cela nous montre l'espace de stockage que chaque type de données utilise lorsqu'il est stocké dans une base de données.
Créer une base de données :
CREATE DATABASE CompareTypes;
Créer un tableau :
USE CompareTypes; CREATE TABLE Datetime2vsDatetime ( TheDateTime datetime, TheDateTime2 datetime2(3) );
Dans ce cas, je crée deux colonnes - l'une est une datetime colonne et l'autre est une datetime2 colonne.
Vérifiez la longueur de la colonne
Vérifiez la longueur (en octets) de chaque colonne :
SELECT COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime2' ) AS 'datetime2', COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime' ) AS 'datetime';
Résultat :
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 7 | 8 | +-------------+------------+
Nous voyons donc que le datetime2 la colonne a une longueur de 7 octets, par rapport à datetime est de 8 octets.
Insérer des données
Examinons maintenant la taille de stockage des valeurs de date et d'heure réelles lorsqu'elles sont stockées dans SQL Server. Nous pouvons utiliser DBCC PAGE()
pour inspecter la page réelle dans le fichier de données.
Mais d'abord, nous devons insérer des données dans nos colonnes.
Insérer des données :
DECLARE @thedatetime2 datetime2 = '2025-05-21 10:15:30.5554444'; INSERT INTO Datetime2vsDatetime ( TheDateTime, TheDateTime2 ) SELECT @thedatetime2, @thedatetime2;
Sélectionnez les données (juste pour les vérifier) :
SELECT * FROM Datetime2vsDatetime;
Résultat :
+-------------------------+-------------------------+ | TheDateTime | TheDateTime2 | |-------------------------+-------------------------| | 2025-05-21 10:15:30.557 | 2025-05-21 10:15:30.555 | +-------------------------+-------------------------+
Utilisation de DBCC PAGE()
Voici où nous utilisons DBCC PAGE()
pour inspecter la page réelle dans le fichier de données.
Tout d'abord, nous allons utiliser DBCC IND()
pour trouver le PagePID :
DBCC IND('CompareTypes', 'dbo.Datetime2vsDatetime', 0);
Résultat (en utilisant la sortie verticale) :
-[ 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
Cela renvoie deux enregistrements. Nous sommes intéressés par le PageType de 1 (le 2e enregistrement). Nous voulons le PagePID de cet enregistrement. Dans ce cas, le PagePID est 320 .
Nous pouvons maintenant prendre ce PagePID et l'utiliser dans ce qui suit :
DBCC TRACEON(3604, -1); DBCC PAGE(CompareTypes, 1, 320, 3);
Cela produit beaucoup de données, mais nous nous intéressons principalement à la partie suivante :
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
Cela montre que datetime utilise une longueur de 8 octets et datetime2(3) utilise 7 octets lorsqu'il est stocké dans une base de données.
Cela renforce donc les arguments en faveur de l'utilisation de datetime2 sur datetime lors de la conception de nouvelles bases de données, en particulier si la taille de stockage est un problème.