DATEADD (Transact-SQL)
Restituisce il valore date specificato con l'intervallo number specificato (interi con segno) aggiunto a un valore datepart specificato del valore date stesso.
Per una panoramica di tutti i tipi di dati e delle funzioni di data e ora Transact-SQL, vedere Funzioni di data e ora (Transact-SQL). Per informazioni ed esempi comuni ai tipi di dati e alle funzioni di data e ora, vedere Utilizzo di dati relativi a data e ora.
Sintassi
DATEADD (datepart , number , date )
Argomenti
datepart
Parte di date a cui viene aggiunto un valore numberinteger. Nella tabella seguente vengono elencati tutti gli argomenti di datepart validi. Variabili definite dall'utente equivalenti non sono valide.datepart
Abbreviazioni
year
yy, yyyy
quarter
qq, q
month
mm, m
dayofyear
dy, y
day
dd, d
week
wk, ww
weekday
dw, w
hour
hh
minute
mi, n
second
ss, s
millisecond
ms
microsecond
mcs
nanosecond
ns
number
Espressione che può essere risolta in un tipo int aggiunto a datepart di date. Le variabili definite dall'utente sono valide.Se un valore viene specificato mediante una frazione decimale, la frazione viene troncata e non arrotondata.
date
Espressione che può essere risolta in un valore di tipo time, date, smalldatetime, datetime, datetime2 o datetimeoffset. I valori di tipo date possono essere costituiti da un'espressione, da un'espressione di colonna, da una variabile definita dall'utente o da un valore letterale stringa. Se l'espressione è un valore letterale stringa, deve essere risolta in un tipo datetime. Per evitare ambiguità, esprimere gli anni nel formato a quattro cifre. Per informazioni sul formato dell'anno a due cifre, vedere Opzione two digit year cutoff.
Tipi restituiti
Il tipo di dati restituito è rappresentato dal tipo di dati dell'argomento date, ad eccezione dei valori letterali stringa.
Il tipo di dati restituito per un valore letterale stringa è datetime. Se la scala dei secondi del valore letterale stringa ha più di tre posizioni (.nnn) o contiene la parte relativa alla differenza di fuso orario, viene generato un errore.
Nota
Se il cast di valori letterali stringa non è eseguito in modo esplicito per il parametro date, le variabili locali che utilizzano un formato di data giorno-mese-anno possono ottenere risultati errati quando DATEADD viene utilizzato insieme ad altre funzioni di data/ora.
Restituzione di un tipo datetime2
DATEADD restituisce un tipo datetime2 quando il parametro date è di tipo datetime2. Quando si utilizzano valori letterali stringa per il parametro date, è necessario eseguirne il cast in modo esplicito nel tipo datetime2 affinché DATEADD restituisca il tipo datetime2.
Argomento datepart
dayofyear, day e weekday restituiscono lo stesso valore.
Ogni valore datepart e le relative abbreviazioni restituiscono lo stesso valore.
Se datepart è month, il mese del valore date ha più giorni del mese restituito e il giorno del valore date non esiste nel mese restituito, viene restituito l'ultimo giorno del mese restituito. Ad esempio, settembre ha 30 giorni. Pertanto, le due istruzioni seguenti restituiscono 2006-09-30 00:00:00.000:
SELECT DATEADD(month, 1, '2006-08-30')
SELECT DATEADD(month, 1, '2006-08-31')
Un argomento number non può superare l'intervallo del tipo int. Nelle istruzioni seguenti, l'argomento per number supera l'intervallo di int di una unità. Viene restituito il messaggio di errore seguente: "Errore di overflow aritmetico durante la conversione dell'espressione nel tipo di dati int".
SELECT DATEADD(year,2147483648, '2006-07-31');
SELECT DATEADD(year,-2147483649, '2006-07-31');
Non è possibile incrementare un argomento date a un valore al di fuori dell'intervallo consentito per il tipo di dati corrispondente. Nelle istruzioni seguenti, il valore number aggiunto al valore date supera l'intervallo del tipo di dati date. Viene restituito il messaggio di errore seguente: "Overflow generato dall'aggiunta di un valore a una colonna 'datetime'".
SELECT DATEADD(year,2147483647, '2006-07-31');
SELECT DATEADD(year,-2147483647, '2006-07-31');
La seconda parte di un valore smalldatetime è sempre 00. Se l'argomento date è smalldatetime, si applicano le condizioni seguenti:
Se datepart corrisponde a second e number è compreso tra -30 e +29, non viene eseguita alcuna aggiunta.
Se datepart corrisponde a second e number è minore di -30 o maggiore di +29, l'aggiunta viene eseguita iniziando da un minuto.
Se datepart corrisponde a millisecond e number è compreso tra -30001 e +29998, non viene eseguita alcuna aggiunta.
Se datepart corrisponde a millisecond e number è minore di -30001 o maggiore di +29998, l'aggiunta viene eseguita iniziando da un minuto.
Osservazioni
È possibile utilizzare DATEADD nell'<elenco> SELECT e nelle clausole WHERE, HAVING, GROUP BY e ORDER BY.
Precisione in secondi frazionari
L'aggiunta a un valore datepart di valori microsecond o nanosecond per i tipi di dati datesmalldatetime, date e datetime non è consentita.
I millisecondi hanno una scala di 3 (.123). I microsecondi hanno una scala di 6 (.123456). I nanosecondi hanno una scala di 9 (.123456789). I tipi di dati time, datetime2e datetimeoffset hanno una scala massima di 7 (.1234567). Se un valore datepart è costituito da nanosecond, number deve essere pari a 100 perché si verifichi l'aumento dei secondi frazionari di date. Un number tra 1 e 49 viene arrotondato per difetto a 0 e un number da 50 a 99 viene arrotondato per eccesso a 100.
Le istruzioni seguenti consentono di aggiungere un valore datepart costituito da millisecond, microsecond o nanosecond.
DECLARE @datetime2 datetime2 = '2007-01-01 13:10:10.1111111'
SELECT '1 millisecond' ,DATEADD(millisecond,1,@datetime2)
UNION ALL
SELECT '2 milliseconds', DATEADD(millisecond,2,@datetime2)
UNION ALL
SELECT '1 microsecond', DATEADD(microsecond,1,@datetime2)
UNION ALL
SELECT '2 microseconds', DATEADD(microsecond,2,@datetime2)
UNION ALL
SELECT '49 nanoseconds', DATEADD(nanosecond,49,@datetime2)
UNION ALL
SELECT '50 nanoseconds', DATEADD(nanosecond,50,@datetime2)
UNION ALL
SELECT '150 nanoseconds', DATEADD(nanosecond,150,@datetime2);
/*
Returns:
1 millisecond 2007-01-01 13:10:10.1121111
2 milliseconds 2007-01-01 13:10:10.1131111
1 microsecond 2007-01-01 13:10:10.1111121
2 microseconds 2007-01-01 13:10:10.1111131
49 nanoseconds 2007-01-01 13:10:10.1111111
50 nanoseconds 2007-01-01 13:10:10.1111112
150 nanoseconds 2007-01-01 13:10:10.1111113
*/
Differenza di fuso orario
L'aggiunta non è consentita per la differenza di fuso orario.
Esempi
A. Incremento di un datepart a intervalli di una unità
Ognuna delle istruzioni seguenti incrementa il valore datepart a intervalli di una unità.
DECLARE @datetime2 datetime2 = '2007-01-01 13:10:10.1111111'
SELECT 'year', DATEADD(year,1,@datetime2)
UNION ALL
SELECT 'quarter',DATEADD(quarter,1,@datetime2)
UNION ALL
SELECT 'month',DATEADD(month,1,@datetime2)
UNION ALL
SELECT 'dayofyear',DATEADD(dayofyear,1,@datetime2)
UNION ALL
SELECT 'day',DATEADD(day,1,@datetime2)
UNION ALL
SELECT 'week',DATEADD(week,1,@datetime2)
UNION ALL
SELECT 'weekday',DATEADD(weekday,1,@datetime2)
UNION ALL
SELECT 'hour',DATEADD(hour,1,@datetime2)
UNION ALL
SELECT 'minute',DATEADD(minute,1,@datetime2)
UNION ALL
SELECT 'second',DATEADD(second,1,@datetime2)
UNION ALL
SELECT 'millisecond',DATEADD(millisecond,1,@datetime2)
UNION ALL
SELECT 'microsecond',DATEADD(microsecond,1,@datetime2)
UNION ALL
SELECT 'nanosecond',DATEADD(nanosecond,1,@datetime2);
/*
Year 2008-01-01 13:10:10.1111111
quarter 2007-04-01 13:10:10.1111111
month 2007-02-01 13:10:10.1111111
dayofyear 2007-01-02 13:10:10.1111111
day 2007-01-02 13:10:10.1111111
week 2007-01-08 13:10:10.1111111
weekday 2007-01-02 13:10:10.1111111
hour 2007-01-01 14:10:10.1111111
minute 2007-01-01 13:11:10.1111111
second 2007-01-01 13:10:11.1111111
millisecond 2007-01-01 13:10:10.1121111
microsecond 2007-01-01 13:10:10.1111121
nanosecond 2007-01-01 13:10:10.1111111
*/
B. Incremento di più livelli di datepart in un'unica istruzione
Ognuna delle istruzioni seguenti incrementa datepart di un valore number abbastanza grande da incrementare anche l'argomento datepart di livello immediatamente più alto di date.
DECLARE @datetime2 datetime2;
SET @datetime2 = '2007-01-01 01:01:01.1111111';
--Statement Result
-------------------------------------------------------------------
SELECT DATEADD(quarter,4,@datetime2); --2008-01-01 01:01:01.110
SELECT DATEADD(month,13,@datetime2); --2008-02-01 01:01:01.110
SELECT DATEADD(dayofyear,365,@datetime2); --2008-01-01 01:01:01.110
SELECT DATEADD(day,365,@datetime2); --2008-01-01 01:01:01.110
SELECT DATEADD(week,5,@datetime2); --2007-02-05 01:01:01.110
SELECT DATEADD(weekday,31,@datetime2); --2007-02-01 01:01:01.110
SELECT DATEADD(hour,23,@datetime2); --2007-01-02 00:01:01.110
SELECT DATEADD(minute,59,@datetime2); --2007-01-01 02:00:01.110
SELECT DATEADD(second,59,@datetime2); --2007-01-01 01:02:00.110
SELECT DATEADD(millisecond,1,@datetime2); --2007-01-01 01:01:01.110
C. Utilizzo di espressioni come argomenti per i parametri number e date
Negli esempi seguenti sono utilizzati tipi diversi di espressioni come argomenti per i parametri number e date.
Indicazione di una colonna come data
Nell'esempio seguente vengono aggiunti 2 giorni a OrderDate per calcolare un nuovo valore di PromisedShipDate.
USE AdventureWorks2008R2;
GO
SELECT SalesOrderID
,OrderDate
,DATEADD(day,2,OrderDate) AS PromisedShipDate
FROM Sales.SalesOrderHeader;
Indicazione di variabili definite dall'utente come argomenti number e date
Nell'esempio seguente vengono specificate variabili definite dall'utente come argomenti number e date.
DECLARE @days int;
DECLARE @datetime datetime;
SET @days = 365;
SET @datetime = '2000-01-01 01:01:01.111'; /* 2000 was a leap year */
SELECT DATEADD(day, @days, @datetime);
Indicazione di una funzione di sistema scalare come valore date
Nell'esempio seguente viene specificata la funzione SYSDATETIME per un valore date.
SELECT DATEADD(month, 1, SYSDATETIME());
Indicazione di sottoquery scalari e funzioni scalari come valori number e date
Nell'esempio seguente vengono utilizzate sottoquery scalari e funzioni scalari, MAX(ModifiedDate) come argomenti number e date. (SELECT TOP 1 BusinessEntityID FROM Person.Person) è un argomento fittizio affinché il parametro number mostri come selezionare un argomento number da un elenco di valori.
USE AdventureWorks2008R2;
GO
SELECT DATEADD(month,(SELECT TOP 1 BusinessEntityID FROM Person.Person),
(SELECT MAX(ModifiedDate) FROM Person.Person));
Indicazione di costanti come argomenti number e date
Nell'esempio seguente vengono utilizzate costanti numeriche e di tipo carattere come argomenti number e date.
SELECT DATEADD(minute, 1, '2007-05-07 09:53:01.0376635');
Indicazione di espressioni numeriche e funzioni di sistema scalari come valori number e date
Nell'esempio seguente sono utilizzate espressioni numeriche (-(10/2)), operatori unari (-), un operatore aritmetico (/) e funzioni di sistema scalari (SYSDATETIME) come argomenti number e date.
SELECT DATEADD(month,-(10/2), SYSDATETIME());
Indicazione di funzioni di rango come argomenti number
Nell'esempio seguente è utilizzata una funzione di rango come argomento number.
USE AdventureWorks2008R2;
GO
SELECT p.FirstName, p.LastName
,DATEADD(day,ROW_NUMBER() OVER (ORDER BY
a.PostalCode),SYSDATETIME()) AS 'Row Number'
FROM Sales.SalesPerson AS s
INNER JOIN Person.Person AS p
ON s.BusinessEntityID = p.BusinessEntityID
INNER JOIN Person.Address AS a
ON a.AddressID = p.BusinessEntityID
WHERE TerritoryID IS NOT NULL
AND SalesYTD <> 0;
Indicazione di una funzione finestra di aggregazione come argomento number
Nell'esempio seguente viene utilizzata una funzione finestra di aggregazione come argomento per number.
USE AdventureWorks2008R2;
GO
SELECT SalesOrderID, ProductID, OrderQty
,DATEADD(day,SUM(OrderQty)
OVER(PARTITION BY SalesOrderID),SYSDATETIME()) AS 'Total'
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN(43659,43664);
GO
D. Utilizzo di DATEADD per impostazioni locali che utilizzano il formato data gma
Negli esempi seguenti viene illustrato come utilizzare i valori letterali stringa con DATEADD per alcune impostazioni locali.
Dimostrazione dei problemi relativi all'utilizzo di un cast implicito di un valore letterale stringa
Nell'esempio seguente viene illustrato ciò che accade quando non viene eseguito in modo esplicito il cast di un valore letterale stringa.
SET LANGUAGE Español;
GO
SELECT DATENAME(m, DATEADD(d, 0,'1987-03-07'));
SELECT DATENAME(m, '1987-03-07');
GO
La prima istruzione SELECT restituisce julio (luglio) per il mese e la seconda restituisce marzo per il mese.
Evitare risultati errati eseguendo il cast del valore letterale stringa in modo esplicito
Nell'esempio seguente viene illustrato come eseguire il cast del parametro date in modo esplicito per evitare risultati errati.
SET LANGUAGE Español;
GO
SELECT DATENAME(m, DATEADD(d, 0, CAST('1987-03-07' AS datetime2)));
SELECT DATENAME(m, '1987-03-07');
GO
Entrambe le istruzioni SELECT restituiscono marzo per il mese.
Utilizzo di una variabile datetime2 al posto di un valore letterale stringa
Nell'esempio seguente viene evitato l'utilizzo diretto di un valore letterale stringa.
SET LANGUAGE Español;
GO
DECLARE @d datetime2 = '1987-03-07';
SELECT DATENAME(m, DATEADD(d, 0, @d));
SELECT DATENAME(m, @d);
GO