Dit artikel onderzoekt de belangrijkste verschillen tussen de datetime en datetime2 gegevenstypen in SQL Server.
Als je niet zeker weet welke je moet gebruiken, gebruik dan datetime2 (zie de voordelen hieronder).
Hier is een tabel met de belangrijkste verschillen tussen deze twee typen.
Functie | datetime | datetime2 |
---|---|---|
SQL-compatibel (ANSI &ISO 8601) | Nee | Ja |
Datumbereik | 1753-01-01 tot 9999-12-31 | 0001-01-01 tot 9999-12-31 |
Tijdbereik | 00:00:00 tot 23:59:59,997 | 00:00:00 tot 23:59:59,999999 |
Tekenlengte | 19 posities minimaal 23 maximaal | 19 posities minimaal 27 maximaal |
Opslaggrootte | 8 bytes | 6 tot 8 bytes, afhankelijk van de precisie* * Plus 1 byte om de precisie op te slaan |
Nauwkeurigheid | Afgerond op stappen van .000, .003 of .007 seconden | 100 nanoseconden |
Door gebruiker gedefinieerde precisie van fractionele seconden | Nee | Ja |
Tijdzoneverschuiving | Geen | Geen |
Bewustwording en behoud van tijdzoneverschuiving | Nee | Nee |
Bewust zomertijd | Nee | Nee |
Voordelen van ‘datetime2’
Zoals te zien is in de bovenstaande tabel, is de datetime2 type heeft veel voordelen ten opzichte van datetime , waaronder:
- grotere periode
- grotere standaard fractionele precisie
- optionele door de gebruiker gespecificeerde precisie
- hogere nauwkeurigheid, zelfs bij gebruik van hetzelfde aantal decimalen als datetime (d.w.z. 3)
- minder opslagruimte bij gebruik van hetzelfde aantal decimalen als datetime , maar met een hogere nauwkeurigheid*
- de optie om 2 bytes minder opslagruimte te gebruiken dan datetime (zij het met een lagere precisie)*
- komt overeen met de SQL-standaarden (ANSI &ISO 8601)
* In sommige gevallen een datetime2 value gebruikt een extra byte om de precisie op te slaan, wat zou resulteren in dezelfde opslaggrootte als datetime bij gebruik van hetzelfde aantal decimalen. Lees verder om hier meer over te weten te komen.
Moet ik 'datetime' of 'datetime2' gebruiken?
Microsoft raadt datetime2 aan over datetime voor nieuw werk (en om dezelfde redenen als hierboven genoemd).
Gebruik daarom datetime2 , tenzij u een specifieke reden heeft om dit niet te doen (zoals werken met een legacy-systeem).
Voorbeeld 1 – Basisvergelijking
Hier is een snel voorbeeld om het fundamentele verschil te demonstreren tussen datetime en 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';
Resultaat:
+-----------------------------+-------------------------+ | datetime2 | datetime | |-----------------------------+-------------------------| | 2025-05-21 10:15:30.5555555 | 2025-05-21 10:15:30.557 | +-----------------------------+-------------------------+
Hier stel ik een datumtijd in variabele naar dezelfde waarde als de datetime2 variabel. Hierdoor wordt de waarde geconverteerd naar datetime en we kunnen dan een SELECT
. gebruiken verklaring om het resultaat te zien.
In dit geval is de datetime2 variabele gebruikt een schaal van 7, wat 7 decimalen betekent. De datetime waarde daarentegen gebruikt slechts 3 decimalen en het laatste fractionele cijfer wordt naar boven afgerond (omdat dit gegevenstype de fractionele seconden rondt op stappen van .000, .003 of .007 seconden).
Voorbeeld 2 – 3 decimalen gebruiken
Als ik de datetime2 . verklein schaal tot 3 (om overeen te komen met datetime ), dit is wat er gebeurt.
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';
Resultaat:
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.556 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
Dus de datetime2 waarde wordt in dit geval ook naar boven afgerond. Het wordt echter alleen naar boven afgerond op 556 – het springt niet naar 557 zoals de datetime waarde wel.
Natuurlijk, de enige reden waarom de datetime2 waarde naar boven wordt afgerond, omdat het volgende cijfer 5 of hoger is. Als we het volgende cijfer verkleinen, wordt er niet afgerond:
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';
Resultaat:
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.555 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
Echter, de datetime waarde wordt nog steeds naar boven afgerond.
Voorbeeld 3 – Waarden instellen uit String Literals
In de vorige voorbeelden is de datetime waarde is toegewezen door deze op dezelfde waarde in te stellen als de datetime2 waarde. Wanneer we dat doen, voert SQL Server een impliciete conversie uit zodat de gegevens "passen" bij het nieuwe gegevenstype.
Als we echter proberen om dezelfde letterlijke tekenreeks toe te wijzen aan de datetime variabele die we hebben toegewezen aan datetime2 , krijgen we een foutmelding:
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';
Resultaat:
Msg 241, Level 16, State 1, Line 5 Conversion failed when converting date and/or time from character string.
Dit komt omdat datetime accepteert alleen letterlijke tekenreeksen die 3 of minder fractionele seconden hebben.
Om dit probleem op te lossen, moeten we het breukdeel verkleinen tot slechts 3 (of minder) decimalen.
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';
Resultaat:
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.555 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
De datetime2 type heeft deze beperking niet, zelfs niet bij gebruik van een schaal van 3.
Voorbeeld 4 – Opslaggrootte
De datetime datatype heeft een vaste opslaggrootte van 8 bytes.
De datetime2 aan de andere kant kan het 6, 7 of 8 bytes zijn, afhankelijk van de nauwkeurigheid.
Bij gebruik van 3 decimalen, datetime2 gebruikt slechts 7 bytes, wat betekent dat het minder opslagruimte gebruikt dan datetime (met meer nauwkeurigheid).
Microsoft stelt echter dat de datetime2 type gebruikt ook 1 extra byte om zijn precisie op te slaan. Dus in dit geval zou het 8 bytes gebruiken. En we kunnen daarom de vorige verklaring herzien door te zeggen dat deze 7, 8 of 9 bytes gebruikt.
Dit hangt echter waarschijnlijk af van of we het in een tabel of in een variabele opslaan en of we het al dan niet converteren naar een binaire constante.
Dit is wat er gebeurt als we de DATALENGTH()
. gebruiken functie om het aantal bytes terug te geven dat voor elk van onze waarden is gebruikt:
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';
Resultaat
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 7 | 8 | +-------------+------------+
Maar als we ze converteren naar varbinary , krijgen we het volgende:
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';
Resultaat
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 8 | 8 | +-------------+------------+
Dus datetime2 gebruikt een extra byte bij conversie naar varbinary , waardoor het dezelfde opslaggrootte krijgt als datetime .
Het volgende voorbeeld laat echter zien dat wanneer de gegevens worden opgeslagen in een databasekolom, we een lengte krijgen van 7 bytes voor datetime2 en 8 bytes voor datetime .
Bij het opslaan van datetime2 waarden in een database, bevat de kolomdefinitie de precisie. In dit geval hebben de waarden in elke rij geen extra byte nodig om de precisie op te slaan, en we kunnen zeggen dat datetime2 gebruikt minder opslagruimte dan datetime wanneer hetzelfde aantal fracties van seconden wordt gebruikt.
Voorbeeld 5 – Opslaggrootte voor opgeslagen gegevens
In dit voorbeeld maak ik een database en gebruik ik COL_LENGTH
om de lengte van elke kolom in bytes te retourneren. Ik voeg dan een datetime2 . in en datetime waarde erin en gebruik DBCC PAGE()
om de lengte van de werkelijke gegevens in het paginabestand te vinden. Dit toont ons de opslagruimte die elk gegevenstype gebruikt wanneer het wordt opgeslagen in een database.
Maak een database:
CREATE DATABASE CompareTypes;
Maak een tabel:
USE CompareTypes; CREATE TABLE Datetime2vsDatetime ( TheDateTime datetime, TheDateTime2 datetime2(3) );
In dit geval maak ik twee kolommen - één is een datetime kolom en de andere is een datetime2 kolom.
Controleer de kolomlengte
Controleer de lengte (in bytes) van elke kolom:
SELECT COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime2' ) AS 'datetime2', COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime' ) AS 'datetime';
Resultaat:
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 7 | 8 | +-------------+------------+
We zien dus dat de datetime2 kolom heeft een lengte van 7 bytes, vergeleken met datetime 's lengte van 8 bytes.
Gegevens invoegen
Laten we nu eens kijken naar de opslaggrootte van de werkelijke datum- en tijdwaarden wanneer ze zijn opgeslagen in SQL Server. We kunnen DBCC PAGE()
. gebruiken om de eigenlijke pagina in het gegevensbestand te inspecteren.
Maar eerst moeten we gegevens in onze kolommen invoegen.
Gegevens invoegen:
DECLARE @thedatetime2 datetime2 = '2025-05-21 10:15:30.5554444'; INSERT INTO Datetime2vsDatetime ( TheDateTime, TheDateTime2 ) SELECT @thedatetime2, @thedatetime2;
Selecteer de gegevens (om het te controleren):
SELECT * FROM Datetime2vsDatetime;
Resultaat:
+-------------------------+-------------------------+ | TheDateTime | TheDateTime2 | |-------------------------+-------------------------| | 2025-05-21 10:15:30.557 | 2025-05-21 10:15:30.555 | +-------------------------+-------------------------+
DBCC PAGE() gebruiken
Hier gebruiken we DBCC PAGE()
om de eigenlijke pagina in het gegevensbestand te inspecteren.
Eerst gebruiken we DBCC IND()
om de PagePID te vinden:
DBCC IND('CompareTypes', 'dbo.Datetime2vsDatetime', 0);
Resultaat (met verticale uitvoer):
-[ 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
Dit levert twee records op. We zijn geïnteresseerd in het PageType van 1 (het 2e record). We willen de PagePID van dat record. In dit geval is de PagePID 320 .
Nu kunnen we die PagePID nemen en gebruiken in het volgende:
DBCC TRACEON(3604, -1); DBCC PAGE(CompareTypes, 1, 320, 3);
Dit levert veel data op, maar we zijn vooral geïnteresseerd in het volgende deel:
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
Dit laat zien dat datetime gebruikt een lengte van 8 bytes en datetime2(3) gebruikt 7 bytes wanneer opgeslagen in een database.
Dit versterkt dus de argumenten voor het gebruik van datetime2 over datetime bij het ontwerpen van nieuwe databases, vooral als de opslaggrootte een probleem is.