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:
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) |
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:
Inoltre, la funzione GETDATE()
SYSTDATETIME()
restituisce la data e l'ora del computer
datetime2
GETDATE()
La funzione SYSTEDATETIMEOFFSET()
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
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:
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
Quaderno
Compasso
datetime
datetime
Nel caso di Penna
Quaderno
WHERE
Compasso
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 Compasso Gomma
Tale comportamento è dovuto alla precisione del tipo datetime
In generale, se vogliamo solo
datetime
dalla mezzanotte della data minore
fino all'ultimo "tick" della data maggiore
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
Nella pagina successiva
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:
Per ottenere finalmente Penna Quaderno Compasso
Le considerazioni fatte finora sono valide anche quando dobbiamo gestire solo informazioni sugli orari
datetime
time
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
date
datetime2
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
datetime
OldTodayFormat
datetime2
NewTodayFormat
DATEADD
datetime
OldTomorrowFormat
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.