Questo articolo esplora le principali differenze tra datetime e dataora2 tipi di dati in SQL Server.
Se non sei sicuro di quale utilizzare, utilizza datetime2 (vedi i suoi vantaggi sotto).
Ecco una tabella che delinea le differenze principali tra questi due tipi.
Funzione | datetime | datetime2 |
---|---|---|
Conforme a SQL (ANSI e ISO 8601) | No | Sì |
Intervallo di date | 01-01-1753 a 31-12-9999 | 0001-01-01 al 31-12-9999 |
Intervallo di tempo | 00:00:00 alle 23:59:59.997 | 00:00:00 alle 23:59:59.9999999 |
Lunghezza del personaggio | 19 posizioni minimo 23 massimo | 19 posizioni minimo 27 massimo |
Dimensioni di archiviazione | 8 byte | Da 6 a 8 byte, a seconda della precisione* * Più 1 byte per memorizzare la precisione |
Precisione | Arrotondato a incrementi di .000, .003 o .007 secondi | 100 nanosecondi |
Precisione al secondo frazionario definita dall'utente | No | Sì |
Offset fuso orario | Nessuno | Nessuno |
Consapevolezza e conservazione della differenza di fuso orario | No | No |
Attenzione all'ora legale | No | No |
Vantaggi di "datetime2"
Come si vede nella tabella sopra, il datetime2 il tipo ha molti vantaggi rispetto a datetime , tra cui:
- intervallo di date più ampio
- precisione frazionaria predefinita maggiore
- precisione specificata dall'utente opzionale
- maggiore precisione, anche utilizzando lo stesso numero di cifre decimali di datetime (cioè 3)
- dimensioni di archiviazione inferiori quando si utilizza lo stesso numero di cifre decimali di datetime , ma con maggiore precisione*
- l'opzione per utilizzare 2 byte di spazio di archiviazione in meno rispetto a datetime (anche se con precisione inferiore)*
- si allinea con gli standard SQL (ANSI e ISO 8601)
* In alcuni casi un datetime2 value utilizza un byte in più per memorizzare la precisione, che risulterebbe nella stessa dimensione di archiviazione di datetime quando si utilizza lo stesso numero di cifre decimali. Continua a leggere per saperne di più.
Devo usare "datetime" o "datetime2"?
Microsoft consiglia datetime2 su data e ora per nuovi lavori (e per gli stessi motivi sopra elencati).
Pertanto, dovresti utilizzare datetime2 , a meno che tu non abbia un motivo specifico per non farlo (come lavorare con un sistema legacy).
Esempio 1 – Confronto di base
Ecco un rapido esempio per dimostrare la differenza fondamentale tra datetime e dataora2 .
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';
Risultato:
+-----------------------------+-------------------------+ | datetime2 | datetime | |-----------------------------+-------------------------| | 2025-05-21 10:15:30.5555555 | 2025-05-21 10:15:30.557 | +-----------------------------+-------------------------+
Qui, ho impostato una data e ora variabile allo stesso valore di datetime2 variabile. Questo fa sì che il valore venga convertito in datetime e possiamo quindi utilizzare un SELECT
dichiarazione per vedere il risultato.
In questo caso, il datetime2 variabile usa una scala di 7, che significa 7 cifre decimali. La data e ora value, invece, utilizza solo 3 cifre decimali e l'ultima cifra frazionaria viene arrotondata per eccesso (poiché questo tipo di dati arrotonda i secondi frazionari a incrementi di .000, .003 o .007 secondi).
Esempio 2:utilizzo di 3 cifre decimali
Se riduco datetime2 scala a 3 (per abbinare datatime ), ecco cosa succede.
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';
Risultato:
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.556 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
Quindi datetime2 anche in questo caso il valore viene arrotondato per eccesso. Tuttavia, viene arrotondato solo a 556 – non passa a 557 come il data/ora il valore lo fa.
Naturalmente, l'unico motivo è datetime2 il valore è arrotondato per eccesso perché la cifra successiva è 5 o superiore. Se riduciamo la cifra seguente, non viene eseguito alcun arrotondamento:
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';
Risultato:
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.555 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
Tuttavia, il data/ora il valore continua ad essere arrotondato per eccesso.
Esempio 3 – Impostazione di valori da stringhe letterali
Negli esempi precedenti, il datatime il valore è stato assegnato impostandolo sullo stesso valore di datetime2 valore. Quando lo facciamo, SQL Server esegue una conversione implicita in modo che i dati "si adattino" al nuovo tipo di dati.
Tuttavia, se proviamo ad assegnare la stessa stringa letterale a datetime variabile assegnata a datetime2 , otteniamo un errore:
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';
Risultato:
Msg 241, Level 16, State 1, Line 5 Conversion failed when converting date and/or time from character string.
Questo perché datetime accetta solo stringhe letterali che hanno 3 o meno secondi frazionari.
Quindi, per ovviare a questo problema, dobbiamo ridurre la parte frazionaria a sole 3 (o meno) cifre decimali.
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';
Risultato:
+-------------------------+-------------------------+ | datetime2 | datetime | |-------------------------+-------------------------| | 2025-05-21 10:15:30.555 | 2025-05-21 10:15:30.557 | +-------------------------+-------------------------+
La dataora2 type non ha questa limitazione, anche quando si utilizza una scala di 3.
Esempio 4 – Dimensioni di archiviazione
La data e ora il tipo di dati ha una dimensione di archiviazione fissa di 8 byte.
La dataora2 d'altra parte, può essere 6, 7 o 8 byte, a seconda della sua precisione.
Quando utilizzi 3 cifre decimali, datetime2 utilizza solo 7 byte, il che significa che utilizza meno spazio di archiviazione di datetime (con maggiore precisione).
Tuttavia, Microsoft afferma che datetime2 type utilizza anche 1 byte in più per memorizzare la sua precisione. Quindi, in questo caso, userebbe 8 byte. E possiamo quindi rivedere l'affermazione precedente dicendo che utilizza 7, 8 o 9 byte.
Tuttavia, questo probabilmente dipende dal fatto che lo stiamo memorizzando in una tabella o in una variabile e se lo stiamo convertendo o meno in una costante binaria.
Ecco cosa succede se utilizziamo DATALENGTH()
funzione per restituire il numero di byte utilizzati per ciascuno dei nostri valori:
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';
Risultato
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 7 | 8 | +-------------+------------+
Ma se li convertiamo in varbinary , otteniamo quanto segue:
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';
Risultato
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 8 | 8 | +-------------+------------+
Quindi dataora2 utilizza un byte in più quando viene convertito in varbinary , portandolo così alla stessa dimensione di archiviazione di datetime .
Tuttavia, l'esempio seguente mostra che quando i dati sono archiviati in una colonna del database, otteniamo una lunghezza di 7 byte per datetime2 e 8 byte per datetime .
Durante la memorizzazione di datetime2 valori in un database, la definizione di colonna include la precisione. In questo caso i valori in ogni riga non hanno bisogno del byte extra per memorizzare la precisione e possiamo dire che datetime2 utilizza meno spazio di archiviazione di datetime quando si utilizza lo stesso numero di secondi frazionari.
Esempio 5 – Dimensioni di archiviazione per i dati archiviati
In questo esempio creo un database e utilizzo COL_LENGTH
per restituire la lunghezza di ciascuna colonna, in byte. Quindi inserisco un datetime2 e data e ora valore in esso e utilizzare DBCC PAGE()
per trovare la lunghezza dei dati effettivi nel file di paging. Questo ci mostra lo spazio di archiviazione utilizzato da ciascun tipo di dati quando viene archiviato in un database.
Crea un database:
CREATE DATABASE CompareTypes;
Crea una tabella:
USE CompareTypes; CREATE TABLE Datetime2vsDatetime ( TheDateTime datetime, TheDateTime2 datetime2(3) );
In questo caso creo due colonne:una è un datetime colonna e l'altra è una datetime2 colonna.
Controlla la lunghezza della colonna
Controlla la lunghezza (in byte) di ogni colonna:
SELECT COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime2' ) AS 'datetime2', COL_LENGTH ( 'dbo.Datetime2vsDatetime' , 'TheDateTime' ) AS 'datetime';
Risultato:
+-------------+------------+ | datetime2 | datetime | |-------------+------------| | 7 | 8 | +-------------+------------+
Quindi vediamo che il datetime2 la colonna ha una lunghezza di 7 byte, rispetto a datetime 's lunghezza di 8 byte.
Inserisci dati
Ora esaminiamo le dimensioni di archiviazione dei valori di data e ora effettivi quando sono archiviati in SQL Server. Possiamo usare DBCC PAGE()
per controllare la pagina effettiva nel file di dati.
Ma prima dobbiamo inserire i dati nelle nostre colonne.
Inserisci dati:
DECLARE @thedatetime2 datetime2 = '2025-05-21 10:15:30.5554444'; INSERT INTO Datetime2vsDatetime ( TheDateTime, TheDateTime2 ) SELECT @thedatetime2, @thedatetime2;
Seleziona i dati (solo per verificarli):
SELECT * FROM Datetime2vsDatetime;
Risultato:
+-------------------------+-------------------------+ | TheDateTime | TheDateTime2 | |-------------------------+-------------------------| | 2025-05-21 10:15:30.557 | 2025-05-21 10:15:30.555 | +-------------------------+-------------------------+
Utilizzo di DBCC PAGE()
Qui è dove usiamo DBCC PAGE()
per controllare la pagina effettiva nel file di dati.
Per prima cosa, utilizzeremo DBCC IND()
per trovare il PagePID:
DBCC IND('CompareTypes', 'dbo.Datetime2vsDatetime', 0);
Risultato (usando l'output verticale):
-[ 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
Questo restituisce due record. Siamo interessati al PageType di 1 (il 2° record). Vogliamo il PagePID da quel record. In questo caso il PagePID è 320 .
Ora possiamo prendere quel PagePID e usarlo nel modo seguente:
DBCC TRACEON(3604, -1); DBCC PAGE(CompareTypes, 1, 320, 3);
Questo produce molti dati, ma siamo principalmente interessati alla parte seguente:
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
Questo mostra che data e ora utilizza una lunghezza di 8 byte e datetime2(3) utilizza 7 byte quando è archiviato in un database.
Quindi questo rafforza la tesi per l'utilizzo di datetime2 su data e ora durante la progettazione di nuovi database, soprattutto se le dimensioni dello spazio di archiviazione sono un problema.