Den här artikeln undersöker de viktigaste skillnaderna mellan datetime och datetime2 datatyper i SQL Server.
Om du inte är säker på vilken du ska använda, använd datetime2 (se dess fördelar nedan).
Här är en tabell som beskriver de viktigaste skillnaderna mellan dessa två typer.
Funktion | datumtid | datetime2 |
---|---|---|
SQL-kompatibel (ANSI &ISO 8601) | Nej | Ja |
Datumintervall | 1753-01-01 till 9999-12-31 | 0001-01-01 till 9999-12-31 |
Tidsintervall | 00:00:00 till 23:59:59.997 | 00:00:00 till 23:59:59.9999999 |
Teckenlängd | 19 positioner minst 23 max | 19 positioner minst 27 max |
Lagringsstorlek | 8 byte | 6 till 8 byte, beroende på precisionen* * Plus 1 byte för att lagra precisionen |
Noggrannhet | Avrundat till steg om 0,000, 0,003 eller 0,007 sekunder | 100 nanosekunder |
Användardefinierad precision på bråkdelssekunder | Nej | Ja |
Tidszonsförskjutning | Inga | Inga |
Medveten om och bevarande av tidszonförskjutning | Nej | Nej |
Medveten om sommartid | Nej | Nej |
Fördelar med "datetime2"
Som framgår av tabellen ovan är datetime2 typ har många fördelar jämfört med datetime , inklusive:
- större datumintervall
- större standard bråkprecision
- valfri användarspecificerad precision
- högre noggrannhet, även när du använder samma antal decimaler som datetime (dvs. 3)
- mindre lagringsstorlek när du använder samma antal decimaler som datetime , men med högre noggrannhet*
- alternativet att använda 2 byte mindre lagringsutrymme än datetime (om än med lägre precision)*
- överensstämmer med SQL-standarderna (ANSI &ISO 8601)
* I vissa fall en datetime2 värde använder en extra byte för att lagra precisionen, vilket skulle resultera i samma lagringsstorlek som datetime när du använder samma antal decimaler. Läs vidare för att ta reda på mer om detta.
Ska jag använda 'datetime' eller 'datetime2'?
Microsoft rekommenderar datetime2 över datumtid för nytt arbete (och av samma skäl som anges ovan).
Därför bör du använda datetime2 , såvida du inte har en specifik anledning att inte göra det (som att arbeta med ett äldre system).
Exempel 1 – Grundläggande jämförelse
Här är ett snabbt exempel för att visa den grundläggande skillnaden mellan datetime och 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 | +-----------------------------+-------------------------+
Här ställer jag in en datumtid variabel till samma värde som datetime2 variabel. Detta gör att värdet konverteras till datetime och vi kan sedan använda en SELECT
uttalande för att se resultatet.
I det här fallet, datetime2 variabeln använder en skala på 7, vilket betyder 7 decimaler. datetime värde å andra sidan använder bara 3 decimaler, och dess sista bråktalssiffra avrundas uppåt (eftersom denna datatyp avrundar bråksekunderna till steg om 0,000, 0,003 eller 0,007 sekunder).
Exempel 2 – Använda 3 decimaler
Om jag minskar datetime2 skala till 3 (för att matcha datetime ), här är vad som händer.
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ärdet avrundas också i detta fall. Det är dock bara avrundat till 556 – den hoppar inte till 557 som datetime värde gör.
Naturligtvis den enda anledningen till datetime2 värdet avrundas uppåt beror på att följande siffra är 5 eller högre. Om vi minskar följande siffra utförs ingen avrundning:
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 datumtid värdet fortsätter att avrundas uppåt.
Exempel 3 – Ställa in värden från strängbokstaver
I de tidigare exemplen, datetime värde tilldelades genom att sätta det till samma värde som datetime2 värde. När vi gör det utför SQL Server en implicit konvertering för att data ska "passa" till den nya datatypen.
Men om vi försöker tilldela samma sträng bokstavligt till datetime variabel som vi tilldelade datetime2 , får vi ett felmeddelande:
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.
Detta beror på att datetime accepterar endast strängliteraler som har 3 eller färre bråksekunder.
Så för att lösa det här problemet måste vi minska bråkdelen till bara 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 typ har inte denna begränsning, även när du använder en skala på 3.
Exempel 4 – Förvaringsstorlek
datetime datatypen har en fast lagringsstorlek på 8 byte.
datetime2 å andra sidan kan den vara antingen 6, 7 eller 8 byte, beroende på dess precision.
När du använder 3 decimaler, datetime2 använder bara 7 byte, vilket betyder att den använder mindre lagringsutrymme än datetime (med större noggrannhet).
Microsoft uppger dock att datetime2 typ använder också 1 extra byte för att lagra dess precision. Så i det här fallet skulle den använda 8 byte. Och vi kan därför revidera det tidigare uttalandet genom att säga att det använder antingen 7, 8 eller 9 byte.
Men detta beror förmodligen på om vi lagrar det i en tabell eller i en variabel, och om vi konverterar det till en binär konstant eller inte.
Här är vad som händer om vi använder DATALENGTH()
funktion för att returnera antalet byte som används för vart och ett av våra värden:
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 om vi konverterar dem till varbinary , får vi följande:
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 använder en extra byte när den konverteras till varbinary , vilket ger den samma lagringsstorlek som datetime .
Följande exempel visar dock att när data lagras i en databaskolumn får vi en längd på 7 byte för datetime2 och 8 byte för datetime .
När du lagrar datetime2 värden i en databas, inkluderar kolumndefinitionen precisionen. I det här fallet behöver värdena i varje rad inte den extra byten för att lagra precisionen, och vi kan säga att datetime2 använder mindre lagringsutrymme än datetime när du använder samma antal bråksekunder.
Exempel 5 – Lagringsstorlek för lagrad data
I det här exemplet skapar jag en databas och använder COL_LENGTH
för att returnera varje kolumns längd, i byte. Jag infogar sedan en datetime2 och datumtid värde i den och använd DBCC PAGE()
för att hitta längden på den faktiska datan i sidfilen. Detta visar oss vilket lagringsutrymme varje datatyp använder när de lagras i en databas.
Skapa en databas:
CREATE DATABASE CompareTypes;
Skapa en tabell:
USE CompareTypes; CREATE TABLE Datetime2vsDatetime ( TheDateTime datetime, TheDateTime2 datetime2(3) );
I det här fallet skapar jag två kolumner – en är en datumtid kolumn och den andra är en datetime2 kolumn.
Kontrollera kolumnlängden
Kontrollera längden (i byte) för varje kolumn:
SELECT COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime2' ) AS 'datetime2', COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime' ) AS 'datetime';
Resultat:
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 7 | 8 | +-------------+------------+
Så vi ser att datetime2 kolumnen har en längd på 7 byte, jämfört med datetime s längd på 8 byte.
Infoga data
Låt oss nu titta på lagringsstorleken för de faktiska datum- och tidsvärdena när de lagras i SQL Server. Vi kan använda DBCC PAGE()
för att inspektera den faktiska sidan i datafilen.
Men först måste vi infoga data i våra kolumner.
Infoga data:
DECLARE @thedatetime2 datetime2 = '2025-05-21 10:15:30.5554444'; INSERT INTO Datetime2vsDatetime ( TheDateTime, TheDateTime2 ) SELECT @thedatetime2, @thedatetime2;
Välj data (bara för att kontrollera det):
SELECT * FROM Datetime2vsDatetime;
Resultat:
+-------------------------+-------------------------+ | TheDateTime | TheDateTime2 | |-------------------------+-------------------------| | 2025-05-21 10:15:30.557 | 2025-05-21 10:15:30.555 | +-------------------------+-------------------------+
Med DBCC PAGE()
Det är här vi använder DBCC PAGE()
för att inspektera den faktiska sidan i datafilen.
Först använder vi DBCC IND()
för att hitta PagePID:
DBCC IND('CompareTypes', 'dbo.Datetime2vsDatetime', 0);
Resultat (med vertikal utdata):
-[ 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
Detta returnerar två rekord. Vi är intresserade av PageType of 1 (den andra posten). Vi vill ha PagePID från den posten. I det här fallet är PagePID 320 .
Nu kan vi ta det PagePID och använda det i följande:
DBCC TRACEON(3604, -1); DBCC PAGE(CompareTypes, 1, 320, 3);
Detta producerar mycket data, men vi är främst intresserade av följande 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
Detta visar att datetime använder en längd på 8 byte och datetime2(3) använder 7 byte när den lagras i en databas.
Så detta förstärker argumenten för att använda datetime2 över datumtid när du designar nya databaser, särskilt om lagringsstorleken är ett problem.