Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Date e orari con SQL Server 2008

I nuovi tipi di dati dedicati a date e orari introdotti in SQL Server 2008 ampliano il supporto per la gestione dei dati nel database e risolvono diversi problemi delle precedenti versioni
I nuovi tipi di dati dedicati a date e orari introdotti in SQL Server 2008 ampliano il supporto per la gestione dei dati nel database e risolvono diversi problemi delle precedenti versioni
Link copiato negli appunti

Sino alla versione 2005, SQL Server forniva unicamente il tipo datetime per memorizzare date e orari: anche se volevamo salvare solo una data (ad esempio la data di nascita di una persona), si doveva comunque inserire un orario non significativo, con un conseguente spreco di spazio di archiviazione e la necessità di ricorrere a particolari "accorgimenti" per effettuare ricerche in campi di questo tipo (come vedremo meglio nel seguito).

Nota: gli esempi commentati in questo articolo sono disponibili nel file zip allegato.

Analogamente, anche quando ci interessava esclusivamente un orario, tale informazione doveva essere accompagnata una data fittizia (a patto, naturalmente, di non salvare le date e gli orari in campi di tipo VARCHAR).

SQL Server 2008 risolve questi problemi introducendo nuovi tipi di dati per la gestione di date e orari, ovvero date, time, datetime2 e datetimeoffset. Essi sono pienamente conformi allo standard SQL, quindi garantiscono la massima portabilità. Come i loro nomi lasciano intuire, i primi due consentono di memorizzare separatamente una data oppure un orario, mentre il datetime2 è una sorta di estensione del datetime tradizionale, di cui aumenta l'intervallo di valori consentiti e la precisione. Il datetimeoffset, infine, aggiunge al datetime2 la possibilità di indicare il fuso di orario di appartenenza.

Questi nuovi tipi di dati sono supportati da tutte le versioni di SQL Server 2008, compresa l'edizione Express. Per utilizzarli con i linguaggi di programmazione .NET, è necessario utilizzare Visual Studio 2008 aggiornato al Service Pack 1 o versione successiva.

Caratteristiche dei nuovi tipi di dati

Le due tabelle seguenti, prese direttamente dalla documentazione in linea, mostrano le caratteristiche principali dei nuovi tipi di dati, a confronto con quelle dei tipi esistenti:

Tabella 1: Formato e intervallo dei tipi di dati del tempo
Tipo di dati Formato Intervallo
time hh:mm:ss[.nnnnnnn] da 00:00:00.0000000 a 23:59:59.9999999
date YYYY-MM-DD da 0001-01-01 a 9999-12-31
smalldatetime YYYY-MM-DD hh:mm:ss da 1900-01-01 a 2079-06-06
datetime YYYY-MM-DD hh:mm:ss[.nnn] da 1753-01-01 a 9999-12-31
datetime2 YYYY-MM-DD hh:mm:ss[.nnnnnnn] da 0001-01-01 00:00:00.0000000 a 9999-12-31 23:59:59.9999999
datetimeoffset YYYY-MM-DD hh:mm:ss[.nnnnnnn] [+|-]hh:mm da 0001-01-01 00:00:00.0000000 a 9999-12-31 23:59:59.9999999 (in UTC)
Tabella 2: Accuratezza e dimensioni dei tipi di dati del tempo
Tipo di dati Accuratezza Dimensioni (in byte) Altro
time 100 nanosecondi da 3 a 5
date 1 giorno 3
smalldatetime 1 minuto 4
datetime 0,00333 secondi 8
datetime2 100 nanosecondi da 6 a 8
datetimeoffset 100 nanosecondi da 8 a 10 Gestisce i fusi orari

Da notare l'aumento di precisione del tipo datetime2 rispetto al datetime: da 0,00333 secondi si passa a soli 100 nanosecondi.

Nella pagina successiva vedremo gli esempi pratici per recuperare la data da un set di dati.

Recuperare data e ora

I seguenti esempi mostrano come recuperare solo la data oppure l'ora corrente a partire dal risultato della funzione GETDATE():

DECLARE @date as DATE, @time AS TIME
SET @date = GETDATE()
SET @time = GETDATE()
SELECT @date AS [Date], @time AS [Time]

Risultato:

Date               Time 
2010-05-17         22:13:14.1630000 

Inoltre, la funzione GETDATE() è stata affiancata da una nuova versione, chiamata SYSTDATETIME(): anche quest'ultima restituisce la data e l'ora del computer in cui è in esecuzione l'istanza di SQL Server, ma lo fa in formato datetime2, quindi con una precisione maggiore rispetto al valore ottenuto con GETDATE().

La funzione SYSTEDATETIMEOFFSET(), invece, è una novità di SQL Server 2008 e restituisce la data e l'ora corrente includendo il fuso orario. Possiamo verificare tali comportamenti con un semplice esempio:

SELECT GETDATE() As OldDateFormat, SYSDATETIME() As NewDateFormat, SYSDATETIMEOFFSET() As [DateTimeOffset]

Questa query produrrà un risultato simile al seguente:

OldDateFormat             NewDateFormat                 DateTimeOffset
2010-04-16 20:51:31.013   2010-04-16 20:51:31.0156250   2010-04-16 20:51:31.0156250 +02:00

Nella pagina successiva vedremo come, lavorando con i nuovi tipi di dato, sia possibile aggirare le limitazioni del vecchio SQL Server.

Lavorare con i nuovi tipi di dati

Il problema

L'introduzione di tipi separati per trattare date e orari in SQL Server 2008 risolve uno dei problemi "storici" di questo database engine, ovvero la necessità di usare"trucchetti" per effettuare ricerche basate su una data o su intervalli di date.

Supponiamo di avere la seguente tabella, in cui la colonna Consegna è di tipo datetime:

ID   Prodotto   Consegna 
1    Gomma      2010-05-22 00:00:00.000 
2    Matita     2010-05-22 15:35:00.000 
3    Penna      2010-05-21 00:00:00.000 
4    Quaderno   2010-05-21 00:00:00.000 
5    Compasso   2010-05-21 10:21:00.000 
6    Righello   2010-05-22 9:50:45.000 

Supponiamo di voler cercare tutti i prodotti consegnati il giorno 21 maggio 2010. Potremmo pensare di scrivere qualcosa del tipo:

SELECT * FROM DateTimeExample WHERE Consegna = '2010-05-21'

Tale interrogazione, tuttavia, restituisce solo due risultati, ovvero Penna e Quaderno, ma non il Compasso. Questo avviene perché, facendo una ricerca in un campo datetime, SQL Server tenta innanzi tutto di convertire la stringa di ricerca ('2010-05-21' nell'esempio) in un valore datetime, aggiungendovi automaticamente il valore 00:00:00.000, ovvero mezzanotte, se non specificato altrimenti.

Nel caso di Penna e Quaderno, l'orario di consegna è proprio la mezzanotte (e dunque rientra nella condizione indicata nella clausola WHERE), mentre il Compasso ha un'ora diversa, per cui non appare tra i risultati dell'interrogazione.

Proviamo quindi ad indicare esplicitamente anche gli orari che ci interessano:

SELECT * FROM DateTimeExample
WHERE Consegna >= '2010-05-21 00:00:00.000' AND Consegna <= '2010-05-21 23:59:59.999'

Ora stiamo cercando tutti i prodotti consegnati dalla mezzanotte alle 23:59:59.999 del giorno 21 maggio 2010. Anche questa interrogazione, però, non produce il risultato desiderato: oltre a Penna, Quaderno e Compasso, tra di essi compare anche Gomma, che ha data di consegna uguale a '2010-05-22 00:00:00.000'.

Tale comportamento è dovuto alla precisione del tipo datetime, che è di 0,00333 secondi, con la conseguenza che il valore '2010-05-21 23:59:59.999' viene "arrotondato" a '2010-05-22 00:00:00.000'.

In generale, se vogliamo solo i prodotti consegnati in un certo giorno, o, più in generale, solo in un intervallo di date, lavorando con una colonna di tipo datetime dobbiamo partire dalla mezzanotte della data minore fino all'ultimo "tick" della data maggiore (23:59:59.997). Nel nostro esempio:

SELECT * FROM DateTimeExample
WHERE Consegna >= '2010-05-21 00:00:00.000' AND Consegna <= '2010-05-21 23:59:59.997'

In alternativa a questo "accorgimento", è possibile utilizzare funzioni di conversione all'interno della clausola WHERE per estrarre solo la porzione di data da un campo datetime. Questa soluzione, però, dovendo applicare una trasformazione a tutti i record elaborati, risulta inefficiente dal punto di vista delle prestazioni.

Nella pagina successiva vedremo la soluzione a questo noioso problema.

La soluzione

Tutti questi problemi si risolvono utilizzando il nuovo campo date. Supponendo di aggiungere una colonna con nome DataConsegna e tipo date, per ottenere tutti i prodotti consegnati il giorno 21 maggio 2010, ci basterà scrivere:

SELECT * FROM DateTimeExample WHERE DataConsegna = '2010-05-21'

Per ottenere finalmente Penna, Quaderno e Compasso, senza dover utilizzare accorgimenti particolari o funzioni di conversione che penalizzano l'efficienza.

Le considerazioni fatte finora sono valide anche quando dobbiamo gestire solo informazioni sugli orari: con SQL Server 2005, se utilizziamo un campo datetime, anche se non siamo interessati all'indicazione del giorno, di fatto siamo obbligati a specificare comunque una data non significativa. Ancora una volta, lavorando con SQL Server 2008 abbiamo la possibilità di utilizzare un campo time, al cui interno inseriremo solo le informazioni che effettivamente ci servono.

Come sappiamo, SQL Server mette a disposizione una serie di funzioni per lavorare con date e orari. Tali funzioni sono state aggiornate per supportare i nuovi tipi di dati introdotti dalla versione 2008. Questo significa che è possibile usare i classici metodi DATEADD, DATEDIFF, DATEPART, YEAR, MONTH, DAY, ecc. anche con date, datetime2 e datetimeoffset.

Diamo un'occhiata al seguente esempio e al corrispondente risultato:

SELECT GETDATE() As OldTodayFormat,
DATEADD(d, 1, GETDATE()) As OldTomorrowFormat,
SYSDATETIME() As NewTodayFormat,
DATEADD(d, 1, SYSDATETIME()) AS NewTomorrowFormat

Risultato:

OldTodayFormat            OldTomorrowFormat	        NewTodayFormat	              NewTomorroFormat
2010-05-14 14:09:42.830   2010-05-15 14:09:42.830   2010-05-14 14:09:42.8318750   2010-05-15 14:09:42.8318750

Abbiamo utilizzato la funzione DATEADD per aggiungere un giorno alla data corrente: quest'ultima viene recuperata sia in formato datetime (OldTodayFormat) sia datetime2 (NewTodayFormat). In base a questo formato, la funzione DATEADD restituirà anch'essa un valore sotto forma di datetime (OldTomorrowFormat) oppure datetime2 (NewTomorrowFormat).

Tutte le altre funzioni si comportano nel solito modo a cui siamo abituati con SQL Server 2005, l'unica differenza è nella precisione dei valori restituiti.

Tutti gli esempi presentati nell'articolo sono disponibili nel file allegato.

Conclusioni

In questo articolo abbiamo presentato i nuovi tipi di dati introdotti da SQL Server 2008 per trattare le date e gli orari. Essi colmano una della "lacune" storiche di questo DBMS e consentono, da una parte, di facilitare la gestione di questo tipo di informazioni , dall'altra di ottenere un'efficienza maggiore e ottimizzare lo spazio di archiviazione, poiché consentono di specificare con maggiore precisione quali dati interessa mantenere.

Anche la documentazione ufficiale di MSDN suggerisce di utilizzare i campi time, date, datetime2 e datetimeoffset per lo sviluppo di nuove applicazioni, proprio in virtù dei vantaggi che portano.

Ti consigliamo anche