Condividi tramite


DATEADD (Transact-SQL)

Viene restituito il valore date specificato con l'intervallo di valori 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 e tipi di dati 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.

Icona di collegamento a un argomentoConvenzioni della sintassi Transact-SQL

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 nella scala dei secondi del valore letterale stringa sono disponibili più di tre posizioni (.nnn) o è contenuta la parte relativa alla differenza di fuso orario, viene generato un errore.

[!NOTA]

Se il cast di valori letterali stringa non viene eseguito in modo esplicito per il parametro date, le impostazioni locali in cui viene utilizzato un formato di data giorno-mese-anno (gma) possono acquisire risultati errati quando DATEADD viene utilizzato insieme ad altre funzioni di data/ora.

Restituzione di un tipo datetime2

Tramite DATEADD viene restituito un tipo datetime2 se il parametro date è un tipo datetime2. Quando si utilizzano valori letterali stringa per il parametro date, è necessario eseguire il cast in modo esplicito di tali valori al tipo datetime2 affinché tramite DATEADD venga restituito un tipo datetime2.

Argomento datepart

Tramite dayofyear, day e weekday viene restituito 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 AdventureWorks;
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 ContactID FROM Person.Contact) è un argomento fittizio affinché il parametro number mostri come selezionare un argomento number da un elenco di valori.

USE AdventureWorks;
GO
SELECT DATEADD(month,(SELECT TOP 1 ContactID FROM Person.Contact),
    (SELECT MAX(ModifiedDate) FROM Person.Contact));

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 AdventureWorks;
GO
SELECT c.FirstName, c.LastName
    ,DATEADD(day,ROW_NUMBER() OVER (ORDER BY
        a.PostalCode),SYSDATETIME()) AS 'Row Number'
FROM Sales.SalesPerson s 
    INNER JOIN Person.Contact c 
        ON s.SalesPersonID = c.ContactID
    INNER JOIN Person.Address a 
        ON a.AddressID = c.ContactID
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 AdventureWorks;
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 le impostazioni locali in cui viene utilizzato il formato data gma

Negli esempi seguenti viene mostrato come utilizzare valori letterali stringa con DATEADD per alcune impostazioni locali.

Illustrazione di trappole nell'utilizzo di un cast implicito di un valore letterale stringa

Nell'esempio seguente vengono illustrate le conseguenze del cast di un valore letterale stringa non eseguito in modo esplicito.

SET LANGUAGE Español;

GO

SELECT DATENAME(m, DATEADD(d, 0,'1987-03-07'));

SELECT DATENAME(m, '1987-03-07');

GO

Per il mese viene restituito julio (luglio) dalla prima istruzione SELECT e marzo (marzo) dalla seconda.

Evitare risultati errati eseguendo il cast in modo esplicito del valore letterale stringa

Nell'esempio seguente viene mostrato come eseguire il cast in modo esplicito del parametro date 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

Dalle due istruzioni SELECT viene restituito marzo (marzo) per il mese.

Utilizzo della 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

Vedere anche

Riferimento