Denne artikel udforsker de vigtigste forskelle mellem dato og klokkeslæt og datetime2 datatyper i SQL Server.
Hvis du ikke er sikker på, hvilken du skal bruge, skal du bruge datetime2 (se fordelene nedenfor).
Her er en tabel, der skitserer de vigtigste forskelle mellem disse to typer.
Funktion | datotid | datetime2 |
---|---|---|
SQL-kompatibel (ANSI &ISO 8601) | Nej | Ja |
Datointerval | 1753-01-01 til 9999-12-31 | 0001-01-01 til 9999-12-31 |
Tidsinterval | 00:00:00 til 23:59:59.997 | 00:00:00 til 23:59:59.9999999 |
Tegnlængde | 19 positioner minimum 23 maksimum | 19 stillinger minimum 27 maksimum |
Lagerstørrelse | 8 bytes | 6 til 8 bytes, afhængig af præcisionen* * Plus 1 byte til at gemme præcisionen |
Nøjagtighed | Afrundet til trin på 0,000, 003 eller 0,007 sekunder | 100 nanosekunder |
Brugerdefineret brøksekundpræcision | Nej | Ja |
Tidszoneforskydning | Ingen | Ingen |
Opmærksomhed og bevarelse af tidszoneforskydning | Nej | Nej |
Sommertid opmærksom på | Nej | Nej |
Fordele ved 'datetime2'
Som det ses i ovenstående tabel, er datetime2 type har mange fordele i forhold til datetime , herunder:
- større datointerval
- større standard brøkpræcision
- valgfri brugerspecificeret præcision
- højere nøjagtighed, selv når du bruger det samme antal decimaler som datotid (dvs. 3)
- mindre lagerstørrelse ved brug af det samme antal decimaler som datotid , dog med højere nøjagtighed*
- muligheden for at bruge 2 bytes mindre lagerplads end datetime (omend med lavere præcision)*
- tilpasser SQL-standarderne (ANSI &ISO 8601)
* I nogle tilfælde en datetime2 værdi bruger en ekstra byte til at gemme præcisionen, hvilket ville resultere i samme lagerstørrelse som datotid ved brug af samme antal decimaler. Læs videre for at finde ud af mere om dette.
Skal jeg bruge 'datetime' eller 'datetime2'?
Microsoft anbefaler datetime2 over datotid for nyt arbejde (og af de samme årsager anført ovenfor).
Derfor bør du bruge datetime2 , medmindre du har en specifik grund til ikke at gøre det (såsom at arbejde med et ældre system).
Eksempel 1 – Grundlæggende sammenligning
Her er et hurtigt eksempel til at demonstrere den grundlæggende forskel mellem datetime og 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';
Resultat:
+-----------------------------+-------------------------+ | datetime2 | datetime | |-----------------------------+-------------------------| | 2025-05-21 10:15:30.5555555 | 2025-05-21 10:15:30.557 | +-----------------------------+-------------------------+
Her indstiller jeg et datotidspunkt variabel til samme værdi som datetime2 variabel. Dette får værdien til at blive konverteret til datetime og vi kan derefter bruge en SELECT
erklæring for at se resultatet.
I dette tilfælde er datetime2 variabel bruger en skala på 7, hvilket betyder 7 decimaler. datoen værdi på den anden side bruger kun 3 decimaler, og dets sidste brøkciffer rundes op (fordi denne datatype afrunder brøksekunderne til trin på 0,000, 003 eller 0,007 sekunder).
Eksempel 2 – Brug af 3 decimaler
Hvis jeg reducerer datetime2 skaler til 3 (for at matche datetime ), her er hvad der sker.
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';
Resultat:
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.556 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
Så datetime2 værdien rundes også op i dette tilfælde. Det er dog kun rundet op til 556 – den hopper ikke til 557 som dato og klokkeslæt værdi gør.
Selvfølgelig er den eneste grund til datetime2 værdien rundes op, fordi det følgende ciffer er 5 eller højere. Hvis vi reducerer følgende ciffer, udføres ingen afrunding:
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';
Resultat:
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.555 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
Men datotidspunktet værdi fortsætter med at blive rundet op.
Eksempel 3 – Indstilling af værdier fra strenge bogstaver
I de foregående eksempler er datetime værdien blev tildelt ved at indstille den til samme værdi som datetime2 værdi. Når vi gør det, udfører SQL Server en implicit konvertering for at dataene "passer" til den nye datatype.
Men hvis vi forsøger at tildele den samme streng bogstavelig til datetime variabel, som vi tildelte datetime2 , får vi en fejl:
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';
Resultat:
Msg 241, Level 16, State 1, Line 5 Conversion failed when converting date and/or time from character string.
Dette er fordi datetime accepterer kun strengliteraler, der har 3 eller færre brøksekunder.
Så for at løse dette problem skal vi reducere brøkdelen til kun 3 (eller færre) decimaler.
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';
Resultat:
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.555 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
datetime2 type har ikke denne begrænsning, selv når du bruger en skala på 3.
Eksempel 4 – Lagerstørrelse
datoen datatypen har en fast lagerstørrelse på 8 bytes.
datetime2 på den anden side kan enten være 6, 7 eller 8 bytes, afhængigt af dens præcision.
Når du bruger 3 decimaler, datetime2 bruger kun 7 bytes, hvilket betyder, at den bruger mindre lagerplads end datetime (med mere nøjagtighed).
Microsoft oplyser dog, at datetime2 type bruger også 1 ekstra byte for at gemme sin præcision. Så i dette tilfælde ville det bruge 8 bytes. Og vi kan derfor revidere den tidligere erklæring ved at sige, at den bruger enten 7, 8 eller 9 bytes.
Dette afhænger dog sandsynligvis af, om vi gemmer det i en tabel eller i en variabel, og om vi konverterer det til en binær konstant eller ej.
Her er, hvad der sker, hvis vi bruger DATALENGTH()
funktion til at returnere antallet af bytes brugt for hver af vores værdier:
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';
Resultat
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 7 | 8 | +-------------+------------+
Men hvis vi konverterer dem til varbinary , får vi følgende:
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';
Resultat
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 8 | 8 | +-------------+------------+
Så datetime2 bruger en ekstra byte, når den konverteres til varbinary , hvilket bringer den til samme lagerstørrelse som datetime .
Det følgende eksempel viser dog, at når dataene er gemt i en databasekolonne, får vi en længde på 7 bytes for datetime2 og 8 bytes for datetime .
Når du gemmer datetime2 værdier i en database, inkluderer kolonnedefinitionen præcisionen. I dette tilfælde behøver værdierne i hver række ikke den ekstra byte til at gemme præcisionen, og vi kan sige, at datetime2 bruger mindre lagerplads end datetime ved brug af det samme antal brøksekunder.
Eksempel 5 – Lagerstørrelse for lagrede data
I dette eksempel opretter jeg en database og bruger COL_LENGTH
for at returnere hver kolonnes længde i bytes. Jeg indsætter derefter en datetime2 og datotid værdi ind i den og brug DBCC PAGE()
for at finde længden af de faktiske data i sidefilen. Dette viser os den lagerplads, hver datatype bruger, når den er gemt i en database.
Opret en database:
CREATE DATABASE CompareTypes;
Opret en tabel:
USE CompareTypes; CREATE TABLE Datetime2vsDatetime ( TheDateTime datetime, TheDateTime2 datetime2(3) );
I dette tilfælde opretter jeg to kolonner – den ene er et datotidspunkt kolonne og den anden er en datetime2 kolonne.
Tjek kolonnelængden
Tjek længden (i bytes) af hver kolonne:
SELECT COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime2' ) AS 'datetime2', COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime' ) AS 'datetime';
Resultat:
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 7 | 8 | +-------------+------------+
Så vi ser, at datetime2 kolonne har en længde på 7 bytes sammenlignet med datetime ’s længde på 8 bytes.
Indsæt data
Lad os nu se på lagerstørrelsen af de faktiske dato- og tidsværdier, når de er gemt i SQL Server. Vi kan bruge DBCC PAGE()
for at inspicere den faktiske side i datafilen.
Men først skal vi indsætte data i vores kolonner.
Indsæt data:
DECLARE @thedatetime2 datetime2 = '2025-05-21 10:15:30.5554444'; INSERT INTO Datetime2vsDatetime ( TheDateTime, TheDateTime2 ) SELECT @thedatetime2, @thedatetime2;
Vælg dataene (bare for at kontrollere dem):
SELECT * FROM Datetime2vsDatetime;
Resultat:
+-------------------------+-------------------------+ | TheDateTime | TheDateTime2 | |-------------------------+-------------------------| | 2025-05-21 10:15:30.557 | 2025-05-21 10:15:30.555 | +-------------------------+-------------------------+
Brug af DBCC PAGE()
Det er her, vi bruger DBCC PAGE()
for at inspicere den faktiske side i datafilen.
Først bruger vi DBCC IND()
for at finde PagePID:
DBCC IND('CompareTypes', 'dbo.Datetime2vsDatetime', 0);
Resultat (ved hjælp af lodret output):
-[ 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
Dette returnerer to poster. Vi er interesserede i PageType of 1 (den 2. post). Vi vil have PagePID fra den post. I dette tilfælde er PagePID 320 .
Nu kan vi tage det PagePID og bruge det i følgende:
DBCC TRACEON(3604, -1); DBCC PAGE(CompareTypes, 1, 320, 3);
Dette producerer en masse data, men vi er primært interesserede i følgende del:
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
Dette viser, at datetime bruger en længde på 8 bytes og datetime2(3) bruger 7 bytes, når den er gemt i en database.
Så dette forstærker argumentet for at bruge datetime2 over datotid når du designer nye databaser, især hvis lagerstørrelse er et problem.