DATEADD (Transact-SQL)
Devuelve un valor de date especificado con el intervalo de number especificado (entero con signo) agregado a un valor de datepart especificado de ese valor de date.
Para obtener una introducción de todos los tipos de datos y funciones de fecha y hora de Transact-SQL, consulte Tipos de datos y funciones de fecha y hora (Transact-SQL). Para obtener información y ejemplos comunes a los tipos de datos y funciones de fecha y hora, consulte Usar datos de fecha y hora.
Sintaxis
DATEADD (datepart , number, date )
Argumentos
datepart
Es una parte de date al que se agrega un integernumber. En la siguiente tabla se recogen los argumentos válidos de datepart. Los equivalentes de variables definidas por el usuario no son válidos.datepart
Abreviaturas
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
Es una expresión que se puede resolver como un valor int que se agrega a un valor datepart de date. Las variables definidas por el usuario son válidas.Si especifica un valor con una fracción decimal, la fracción se trunca y no se redondea.
date
Es una expresión que se puede resolver como un valor time, date, smalldatetime, datetime, datetime2 o datetimeoffset. date puede ser una expresión, una expresión de columna, una variable definida por el usuario o un literal de cadena. Si la expresión es un literal de cadena, debe tener como resultado un valor datetime. Para evitar la ambigüedad, utilice años de cuatro dígitos. Parta obtener información sobre los años de dos dígitos, consulte two digit year cutoff (opción).
Tipos de valor devueltos
El tipo de datos de retorno es el tipo de datos del argumento date, salvo los literales de cadena.
El tipo de datos de retorno para un literal de cadena es datetime. Se producirá un error si la escala de segundos del literal de cadena tiene más de tres posiciones (.nnn) o contiene la parte del desplazamiento de zona horaria.
[!NOTA]
Si los literales de cadena no se convierten explícitamente para el parámetro date, los locales que utilizan un formato de fecha día-mes-año (dma) pueden obtener resultados incorrectos cuando DATEADD se utiliza junto con otras funciones de fecha y hora.
Devolver un tipo datetime2
DATEADD devuelve un tipo datetime2 cuando el parámetro date es un tipo datetime2. Cuando se utilizan literales de cadena para el parámetro date, se deben convertir explícitamente a un tipo datetime2 para que DATEADD devuelva un tipo datetime2.
Valor devuelto
Argumento datepart
dayofyear, day y weekday devuelven el mismo valor.
Cada datepart y sus abreviaturas devuelven el mismo valor.
Si datepart es month y el mes date tiene más días que el mes de retorno y el día date no existe en el mes de retorno, se devuelve el último día del mes de retorno. Por ejemplo, septiembre tiene 30 días; por consiguiente, las dos instrucciones siguientes devuelven 2006-09-30 00:00:00.000:
SELECT DATEADD(month, 1, '2006-08-30')
SELECT DATEADD(month, 1, '2006-08-31')
Argumento number
El argumento number no puede superar el intervalo de int. En las instrucciones siguientes, el argumento para number supera el intervalo de int por 1. Se devuelve el mensaje de error siguiente: "Error de desbordamiento aritmético al convertir la expresión al tipo de datos int."
SELECT DATEADD(year,2147483648, '2006-07-31');
SELECT DATEADD(year,-2147483649, '2006-07-31');
Argumento date
El argumento date no se puede incrementar a un valor fuera del intervalo de su tipo de datos. En las instrucciones siguientes, el valor number que se agrega al valor de date supera el intervalo del tipo de datos date. Se devuelve el mensaje de error siguiente: "Al agregar un valor a una columna 'datetime' se originó un desbordamiento."
SELECT DATEADD(year,2147483647, '2006-07-31');
SELECT DATEADD(year,-2147483647, '2006-07-31');
Valores devueltos para una fecha smalldatetime y datepart de un segundo o fracciones de segundo
La parte correspondiente a los segundos de un valor smalldatetime siempre es 00. Si date es smalldatetime, se aplica lo siguiente:
Si datepart es second y number oscila entre -30 y +29, no se realiza ninguna adición.
Si datepart es second y number es inferior a -30 o superior a +29, la suma se realiza empezando por un minuto.
Si datepart es millisecond y number oscila entre -30001 y +29998, no se realiza ninguna suma.
Si datepart es millisecond y number es inferior a -30001 o superior a +29998, la suma se realiza empezando por un minuto.
Notas
DATEADD se puede utilizar en las cláusulas SELECT <lista>, WHERE, HAVING, GROUP BY y ORDER BY.
Precisión de fracciones de segundo
La suma para los tipos de datos datepart de microsecond o nanosecond para datesmalldatetime, date y datetime no está permitida.
Los milisegundos tienen una escala de 3 (0,123). Los microsegundos tienen una escala de 6 (0,123456). Los nanosegundos tienen una escala de 9 (0,123456789). Los tipos de datos time, datetime2 y datetimeoffset tienen una escala máxima de 7 (0,1234567). Si datepart es nanosecond, number debe ser 100 antes de que las fracciones de segundo de date aumenten. Un number entre 1 y 49 se redondea por defecto en 0 y un número de 50 a 99 se redondea por exceso en 100.
Las instrucciones siguientes agregan un datepart de 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
*/
Desplazamiento de zona horaria
La suma no se permite para el desplazamiento de zona horaria.
Ejemplos
A. Aumentar datepart en un intervalo de 1
Cada una de las instrucciones siguientes incrementa datepart en un intervalo de 1.
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. Aumentar más de un nivel de datepart en una instrucción
Cada una de las instrucciones siguientes incrementa datepart en un number los suficientemente grande para también incrementar el datepart más alto siguiente de 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. Utilizar las expresiones como argumentos para los parámetros number y date
Los ejemplos siguientes utilizan tipos diferentes de expresiones como argumentos para los parámetros number y date.
Especificar una columna como fecha
El ejemplo siguiente agrega 2 días a cada OrderDate para calcular un nuevo PromisedShipDate.
USE AdventureWorks;
GO
SELECT SalesOrderID
,OrderDate
,DATEADD(day,2,OrderDate) AS PromisedShipDate
FROM Sales.SalesOrderHeader;
Especificar las variables definidas por el usuario como number y date
El ejemplo siguiente especifica las variables definidas por el usuario como argumentos para number y 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);
Especificar la función de sistema escalar como date
En el siguiente ejemplo se especifica la palabra clave SYSDATETIME para date.
SELECT DATEADD(month, 1, SYSDATETIME());
Especificar subconsultas y funciones escalares como number y date
El siguiente ejemplo utiliza subconsultas escalares y funciones escalares ms177499(v=sql.100).md, MAX(ModifiedDate) como argumentos para number y date. (SELECT TOP 1 ContactID FROM Person.Contact) es un argumento artificial para el parámetro number que se utiliza para mostrar cómo seleccionar un argumento number de una lista de valores.
USE AdventureWorks;
GO
SELECT DATEADD(month,(SELECT TOP 1 ContactID FROM Person.Contact),
(SELECT MAX(ModifiedDate) FROM Person.Contact));
Especificar las constantes como number y date
EL siguiente ejemplo utilizar constantes numéricas y de caracteres como argumentos para number y date.
SELECT DATEADD(minute, 1, '2007-05-07 09:53:01.0376635');
Especificar expresiones numéricas y funciones de sistema escalares como number y date
El ejemplo siguiente utiliza expresiones numéricas (-(10/2)), operadores unarios (-), un operador aritmético (/) y las funciones de sistema escalares (SYSDATETIME) como argumentos para number y date.
SELECT DATEADD(month,-(10/2), SYSDATETIME());
Especificar las funciones de clasificación como number
El ejemplo siguiente utiliza una función de clasificación como argumentos para 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;
Especificar una función de ventana agregada como number
En el ejemplo siguiente se utiliza una función de agregado como argumento para 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. Utilizar DATEADD para configuraciones regionales que utilizan el formato de fecha dma
En los siguientes ejemplos se muestra cómo utilizar literales de cadena con DATEADD para algunas configuraciones regionales.
Mostrar los riesgos que supone el uso de una conversión implícita de un literal de cadena
En el siguiente ejemplo se muestra lo que sucede cuando un literal de cadena no se convierte explícitamente.
SET LANGUAGE Español;
GO
SELECT DATENAME(m, DATEADD(d, 0,'1987-03-07'));
SELECT DATENAME(m, '1987-03-07');
GO
La primera instrucción SELECT devuelve julio para el mes y la segunda instrucción SELECT devuelve marzo para el mes.
Evitar resultados erróneos mediante la conversión explícita del literal de cadena
En el siguiente ejemplo se muestra cómo convertir explícitamente el parámetro date para evitar resultados erróneos.
SET LANGUAGE Español;
GO
SELECT DATENAME(m, DATEADD(d, 0, CAST('1987-03-07' AS datetime2)));
SELECT DATENAME(m, '1987-03-07');
GO
Ambas instrucciones SELECT devuelven marzo para el mes.
Utilizar una variable datetime2 en lugar de un literal de cadena
En el siguiente ejemplo se evita el uso directo de un literal de cadena.
SET LANGUAGE Español;
GO
DECLARE @d datetime2 = '1987-03-07';
SELECT DATENAME(m, DATEADD(d, 0, @d));
SELECT DATENAME(m, @d);
GO