sql >> Databáze >  >> RDS >> Sqlserver

datetime vs datetime2 v SQL Server:Jaký je rozdíl?

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ě.


  1. Vyberte poslední řádek v MySQL

  2. Android program pro převod databáze SQLite do excelu

  3. Jak změnit mysql na mysqli?

  4. CHYBA:povolení odepřeno pro sekvenci cities_id_seq pomocí Postgres