Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

datetime vs smalldatetime in SQL Server:qual è la differenza?

Questo articolo esplora le principali differenze tra datetime e smalldatetime tipi di dati in SQL Server.

Entrambi i tipi di dati vengono utilizzati per memorizzare i valori di data e ora, tuttavia esistono differenze tra i due. Nella maggior parte dei casi è meglio evitare entrambi i tipi e utilizzare datetime2 invece (anche Microsoft consiglia questo). In ogni caso, ecco un confronto di questi due tipi di dati.

La tabella seguente delinea alcune somiglianze e differenze chiave tra questi due tipi di dati.

Funzione smalldatetime datetime
Conforme a SQL (ANSI e ISO 8601) No No
Intervallo di date 01-01-1900 fino a 06-06-2079 01-01-1753 a 31-12-9999
Intervallo di tempo dalle 00:00:00 alle 23:59:59 00:00:00 fino alle 23:59:59.997
Lunghezza del personaggio 19 posizioni al massimo 19 posizioni minimo
23 massimo
Dimensioni di archiviazione 4 byte, fissi 8 byte, fissi
Precisione Un minuto Arrotondato a incrementi di .000, .003 o .007 secondi
Precisione frazionaria dei secondi No
Precisione al secondo frazionario definita dall'utente No No
Offset fuso orario Nessuno Nessuno
Consapevolezza e conservazione della differenza di fuso orario No No
Attenzione all'ora legale No No

Devo usare "datetime" o "smalldatetime"?

Microsoft sconsiglia di utilizzare entrambi questi tipi di dati per il nuovo lavoro. Dovresti usarli solo se hai una buona ragione per farlo.

Ma se dovessi scegliere, la tua decisione verrebbe probabilmente presa soppesando la precisione e l'accuratezza extra di datetime rispetto ai requisiti di archiviazione inferiori di smalldatetime .

In altre parole, se non hai bisogno di precisione ai secondi, smalldatetime farà il lavoro utilizzando solo metà dello spazio di archiviazione. D'altra parte, se hai bisogno di precisione al secondo (o anche ad alcuni secondi frazionari), dovrai utilizzare datetime .

In ogni caso, Microsoft consiglia di utilizzare data , tempo , dataora2 o datetimeoffset per un nuovo lavoro.

Vedi smalldatetime rispetto a dataora2 e data e ora rispetto a dataora2 per vedere come ciascuno di questi tipi si confronta con datetime2 .

Esempio 1 – Confronto di base

Ecco un rapido esempio per dimostrare la differenza fondamentale tra datetime e smalldatetime .

DECLARE 
  @thedatetime datetime, 
  @thesmalldatetime smalldatetime;
SET @thedatetime = '2025-05-21 10:15:30.555';
SET @thesmalldatetime = @thedatetime;
SELECT 
  @thedatetime AS 'datetime',
  @thesmalldatetime AS 'smalldatetime';

Risultato:

+-------------------------+---------------------+
| datetime                | smalldatetime       |
|-------------------------+---------------------|
| 2025-05-21 10:15:30.557 | 2025-05-21 10:16:00 |
+-------------------------+---------------------+

Qui ho impostato un smalldatetime variabile allo stesso valore di datetime variabile. Questo fa sì che il valore venga convertito in smalldatetime e possiamo quindi utilizzare un SELECT istruzione per vedere il valore effettivo che è stato assegnato a ciascuna variabile.

In questo caso, entrambe le variabili arrotondano il valore. Ma sono arrotondati in modo diverso.

La data e ora variabile arrotonda per eccesso la parte dei secondi frazionari. Questo perché datetime arrotonda sempre a incrementi di .000, .003 o .007 secondi.

Il smalldatetime variabile d'altra parte, arrotonda per eccesso i minuti parte. Non solo, la parte dei secondi è azzerata. Questo è prevedibile, perché la documentazione ufficiale di Microsoft afferma che smalldatetime L'ora è ...basata su un giorno di 24 ore, con secondi sempre zero (:00) e senza secondi frazionari .

Quindi possiamo vedere che il datetime type fornisce un valore di data/ora più preciso e accurato.

Esempio 2 – Impostazione di valori da stringhe letterali

Negli esempi precedenti, il smalldatetime valore è stato assegnato impostandolo sullo stesso valore di datetime valore. Quando lo facciamo, SQL Server esegue una conversione implicita in modo che i dati "si adattino" al nuovo tipo di dati.

A quanto pare, possiamo anche impostare smalldatetime variabile alla stessa stringa letterale che include i secondi frazionari (anche se questo tipo di dati non memorizza i secondi frazionari).

Ecco un esempio in cui faccio proprio questo:

DECLARE 
  @thedatetime datetime, 
  @thesmalldatetime smalldatetime;
SET @thedatetime = '2025-05-21 10:15:30.555';
SET @thesmalldatetime = '2025-05-21 10:15:30.555';
SELECT 
  @thedatetime AS 'datetime',
  @thesmalldatetime AS 'smalldatetime';

Risultato:

+-------------------------+---------------------+
| datetime                | smalldatetime       |
|-------------------------+---------------------|
| 2025-05-21 10:15:30.557 | 2025-05-21 10:16:00 |
+-------------------------+---------------------+

Naturalmente, il risultato è lo stesso quando selezioniamo i valori:smalldatetime il valore non mostra i secondi frazionari, i secondi sono zero e i minuti vengono arrotondati per eccesso.

Tuttavia, se utilizziamo più di 3 cifre decimali, entrambi i tipi di dati restituiranno un errore.

Errore per data e ora :

DECLARE 
  @thedatetime datetime, 
  @thesmalldatetime smalldatetime;
SET @thedatetime = '2025-05-21 10:15:30.5555';
SET @thesmalldatetime = '2025-05-21 10:15:30.5555';
SELECT 
  @thedatetime AS 'datetime',
  @thesmalldatetime AS 'smalldatetime';

Risultato:

Msg 241, Level 16, State 1, Line 4
Conversion failed when converting date and/or time from character string.

Errore per smalldatetime :

DECLARE 
  @thedatetime datetime, 
  @thesmalldatetime smalldatetime;
SET @thedatetime = '2025-05-21 10:15:30.5555';
SET @thesmalldatetime = '2025-05-21 10:15:30.5555';
SELECT 
  @thedatetime AS 'datetime',
  @thesmalldatetime AS 'smalldatetime';

Risultato:

Msg 295, Level 16, State 3, Line 5
Conversion failed when converting character string to smalldatetime data type.

Esempio 3 – Dimensioni di archiviazione

Il smalldatetime il tipo di dati ha una dimensione di archiviazione fissa di 4 byte. Questo è uno dei pochi vantaggi smalldatetime ha più di data e ora , che ha una dimensione di archiviazione fissa di 8 byte.

Possiamo controllare la dimensione dello spazio di archiviazione utilizzando il DATALENGTH() funzione per restituire il numero di byte utilizzati per ciascuno dei nostri valori:

DECLARE 
  @thedatetime datetime, 
  @thesmalldatetime smalldatetime;
SET @thedatetime = '2025-05-21 10:15:30.123';
SET @thesmalldatetime = @thedatetime;
SELECT 
  DATALENGTH(@thedatetime) AS 'datetime',
  DATALENGTH(@thesmalldatetime) AS 'smalldatetime';

Risultato

+------------+-----------------+
| datetime   | smalldatetime   |
|------------+-----------------|
| 8          | 4               |
+------------+-----------------+

Otteniamo lo stesso risultato anche se li convertiamo in varbinary , che è più rappresentativo di come sono effettivamente archiviati nel database:

DECLARE 
  @thedatetime datetime, 
  @thesmalldatetime smalldatetime;
SET @thedatetime = '2025-05-21 10:15:30.123';
SET @thesmalldatetime = @thedatetime;
SELECT 
  DATALENGTH(CAST(@thedatetime AS varbinary(10))) AS 'datetime',
  DATALENGTH(CAST(@thesmalldatetime AS varbinary(10))) AS 'smalldatetime';

Risultato

+------------+-----------------+
| datetime   | smalldatetime   |
|------------+-----------------|
| 8          | 4               |
+------------+-----------------+