Tento článek zkoumá hlavní rozdíly mezi datetime a datetime2 datové typy na serveru SQL.
Pokud si nejste jisti, který z nich použít, použijte datetime2 (viz jeho výhody níže).
Zde je tabulka, která uvádí hlavní rozdíly mezi těmito dvěma typy.
Funkce | datum a čas | datetime2 |
---|---|---|
Vyhovující SQL (ANSI &ISO 8601) | Ne | Ano |
Časové období | 1753-01-01 až 9999-12-31 | 0001-01-01 až 9999-12-31 |
Časový rozsah | 00:00:00 až 23:59:59.997 | 00:00:00 až 23:59:59.9999999 |
Délka znaků | Minimálně 19 pozic Maximálně 23 | Minimálně 19 pozic Maximálně 27 |
Velikost úložiště | 8 bajtů | 6 až 8 bajtů, v závislosti na přesnosti* * Plus 1 bajt pro uložení přesnosti |
Přesnost | Zaokrouhleno na přírůstky 0,000, 003 nebo 007 sekund | 100 nanosekund |
Uživatelsky definovaná přesnost na zlomek sekund | Ne | Ano |
Posun časového pásma | Žádné | Žádné |
Sledování a zachování posunu časového pásma | Ne | Ne |
Sledování letního času | Ne | Ne |
Výhody ‚datetime2‘
Jak je vidět v tabulce výše, datetime2 typ má mnoho výhod oproti datetime , včetně:
- větší časové období
- větší výchozí zlomková přesnost
- volitelná přesnost zadaná uživatelem
- vyšší přesnost, a to i při použití stejného počtu desetinných míst jako datetime (tj. 3)
- menší velikost úložiště při použití stejného počtu desetinných míst jako datetime , ale s vyšší přesností*
- možnost použít o 2 bajty méně úložného prostoru než datetime (i když s nižší přesností)*
- je v souladu se standardy SQL (ANSI a ISO 8601)
* V některých případech datetime2 value používá k uložení přesnosti bajt navíc, což by vedlo ke stejné velikosti úložiště jako datetime při použití stejného počtu desetinných míst. Čtěte dále a dozvíte se o tom více.
Mám použít „datetime“ nebo „datetime2“?
Společnost Microsoft doporučuje datetime2 přes datum a čas pro novou práci (a ze stejných důvodů uvedených výše).
Proto byste měli použít datetime2 , pokud k tomu nemáte konkrétní důvod (například práce se starším systémem).
Příklad 1 – Základní srovnání
Zde je rychlý příklad demonstrující základní rozdíl mezi datetime a 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';
Výsledek:
+-----------------------------+-------------------------+ | datetime2 | datetime | |-----------------------------+-------------------------| | 2025-05-21 10:15:30.5555555 | 2025-05-21 10:15:30.557 | +-----------------------------+-------------------------+
Zde nastavím datum a čas proměnnou na stejnou hodnotu jako datetime2 variabilní. To způsobí, že se hodnota převede na datetime a pak můžeme použít SELECT
prohlášení, abyste viděli výsledek.
V tomto případě datetime2 proměnná používá stupnici 7, což znamená 7 desetinných míst. datum a čas value na druhé straně používá pouze 3 desetinná místa a její poslední desetinná číslice je zaokrouhlena nahoru (protože tento datový typ zaokrouhluje zlomky sekund na přírůstky 0,000, 003 nebo 007 sekund).
Příklad 2 – Použití 3 desetinných míst
Pokud snížím datetime2 měřítko na 3 (aby odpovídalo datetime ), co se stane.
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';
Výsledek:
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.556 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
Tedy datetime2 hodnota se v tomto případě také zaokrouhluje nahoru. Je však zaokrouhleno pouze na 556 – nepřeskočí na 557 jako datum a čas hodnota ano.
Samozřejmě jediným důvodem je datetime2 hodnota je zaokrouhlena nahoru, protože následující číslice je 5 nebo vyšší. Pokud zmenšíme následující číslici, žádné zaokrouhlení se neprovede:
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';
Výsledek:
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.555 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
Nicméně datum a čas hodnota se nadále zaokrouhluje nahoru.
Příklad 3 – Nastavení hodnot z řetězcových literálů
V předchozích příkladech datetime hodnota byla přiřazena nastavením na stejnou hodnotu jako datetime2 hodnota. Když to uděláme, SQL Server provede implicitní převod, aby data „seděla“ novému datovému typu.
Pokud se však pokusíme přiřadit stejný řetězcový literál k datetime proměnnou, kterou jsme přiřadili datetime2 , dostaneme chybu:
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';
Výsledek:
Msg 241, Level 16, State 1, Line 5 Conversion failed when converting date and/or time from character string.
Důvodem je datum a čas přijímá pouze řetězcové literály, které mají 3 nebo méně zlomkových sekund.
Abychom tento problém překonali, musíme zmenšit zlomkovou část na pouhá 3 (nebo méně) desetinná místa.
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';
Výsledek:
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.555 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
datetime2 typ nemá toto omezení, a to ani při použití stupnice 3.
Příklad 4 – Velikost úložiště
datum a čas datový typ má pevnou velikost úložiště 8 bajtů.
datetime2 na druhé straně může být buď 6, 7 nebo 8 bajtů, v závislosti na jeho přesnosti.
Při použití 3 desetinných míst datetime2 používá pouhých 7 bajtů, což znamená, že využívá méně úložného prostoru než datetime (s větší přesností).
Společnost Microsoft však uvádí, že datetime2 typ také používá 1 bajt navíc k uložení své přesnosti. V tomto případě by tedy použil 8 bajtů. A proto můžeme revidovat předchozí tvrzení tím, že říká, že používá buď 7, 8 nebo 9 bajtů.
To však pravděpodobně závisí na tom, zda ji ukládáme do tabulky nebo do proměnné a zda ji převádíme na binární konstantu.
Zde je to, co se stane, když použijeme DATALENGTH()
funkce, která vrátí počet bajtů použitých pro každou z našich hodnot:
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';
Výsledek
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 7 | 8 | +-------------+------------+
Pokud je ale převedeme na varbinární , dostaneme následující:
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';
Výsledek
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 8 | 8 | +-------------+------------+
Takže datetime2 používá při převodu na varbinary bajt navíc , čímž se ukládá na stejnou velikost úložiště jako datetime .
Následující příklad však ukazuje, že když jsou data uložena ve sloupci databáze, získáme délku 7 bajtů pro datetime2 a 8 bajtů pro datum a čas .
Při ukládání datetime2 hodnoty v databázi, definice sloupce zahrnuje přesnost. V tomto případě hodnoty v každém řádku nepotřebují extra bajt k uložení přesnosti a můžeme říci, že datetime2 využívá méně úložného prostoru než datetime při použití stejného počtu zlomkových sekund.
Příklad 5 – Velikost úložiště pro uložená data
V tomto příkladu vytvořím databázi a použiji COL_LENGTH
vrátit délku každého sloupce v bajtech. Poté vložím datetime2 a datum a čas do něj a použijte DBCC PAGE()
zjistit délku skutečných dat v souboru stránky. To nám ukazuje úložný prostor, který jednotlivé typy dat využívají, když jsou uloženy v databázi.
Vytvořte databázi:
CREATE DATABASE CompareTypes;
Vytvořte tabulku:
USE CompareTypes; CREATE TABLE Datetime2vsDatetime ( TheDateTime datetime, TheDateTime2 datetime2(3) );
V tomto případě vytvořím dva sloupce – jeden je datetime a druhý je datetime2 sloupec.
Zkontrolujte délku sloupce
Zkontrolujte délku (v bajtech) každého sloupce:
SELECT COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime2' ) AS 'datetime2', COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime' ) AS 'datetime';
Výsledek:
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 7 | 8 | +-------------+------------+
Vidíme tedy, že datetime2 sloupec má délku 7 bajtů ve srovnání s datetime 's délka 8 bajtů.
Vložit data
Nyní se podívejme na velikost úložiště skutečných hodnot data a času, když jsou uloženy na serveru SQL. Můžeme použít DBCC PAGE()
zkontrolovat skutečnou stránku v datovém souboru.
Nejprve však musíme do našich sloupců vložit data.
Vložit data:
DECLARE @thedatetime2 datetime2 = '2025-05-21 10:15:30.5554444'; INSERT INTO Datetime2vsDatetime ( TheDateTime, TheDateTime2 ) SELECT @thedatetime2, @thedatetime2;
Vyberte data (jen pro kontrolu):
SELECT * FROM Datetime2vsDatetime;
Výsledek:
+-------------------------+-------------------------+ | TheDateTime | TheDateTime2 | |-------------------------+-------------------------| | 2025-05-21 10:15:30.557 | 2025-05-21 10:15:30.555 | +-------------------------+-------------------------+
Použití DBCC PAGE()
Zde používáme DBCC PAGE()
zkontrolovat skutečnou stránku v datovém souboru.
Nejprve použijeme DBCC IND()
k nalezení PagePID:
DBCC IND('CompareTypes', 'dbo.Datetime2vsDatetime', 0);
Výsledek (při použití vertikálního výstupu):
-[ 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
Tím se vrátí dva záznamy. Zajímá nás PageType 1 (druhý záznam). Chceme PagePID z tohoto záznamu. V tomto případě je PagePID 320 .
Nyní můžeme vzít toto PagePID a použít jej v následujícím:
DBCC TRACEON(3604, -1); DBCC PAGE(CompareTypes, 1, 320, 3);
To produkuje spoustu dat, ale nás zajímá hlavně následující část:
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
To ukazuje, že datum a čas používá délku 8 bajtů a datetime2(3) používá 7 bajtů při uložení v databázi.
Takže to podporuje použití datetime2 přes datum a čas při navrhování nových databází, zejména pokud jde o velikost úložiště.