DATEADD (Transact-SQL)
Devuelve un valor date con el intervalo number especificado (entero con signo) agregado a un valor datepart especificado de ese valor date.
Para obtener una introducción de todos los tipos de datos y funciones de fecha y hora de Transact-SQL, consulte 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.
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 ajuste de zona horaria.
Nota |
|---|
Si los literales de cadena no se convierten explícitamente para el parámetro date, las configuraciones regionales que usen un formato de fecha día-mes-año (dma) quizá obtengan resultados incorrectos cuando se use DATEADD junto con las 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 usen literales de cadena para el parámetro date, debe convertirlos explícitamente a un tipo datetime2 para que DATEADD devuelva un tipo datetime2.
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')
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');
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');
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.
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 */
Ajuste de zona horaria
La suma no se permite para el ajuste de zona horaria.
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 AdventureWorks2008R2;
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 , MAX(ModifiedDate) como argumentos para number y date. (SELECT TOP 1 BusinessEntityID FROM Person.Person) 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 AdventureWorks2008R2;
GO
SELECT DATEADD(month,(SELECT TOP 1 BusinessEntityID FROM Person.Person),
(SELECT MAX(ModifiedDate) FROM Person.Person));
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 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;
Especificar una función de agregado como number
En el ejemplo siguiente se usa una función de agregado como argumento para 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. Usar DATEADD para configuraciones regionales que usen el formato de fecha dma
En los siguientes ejemplos se muestra cómo usar literales de cadena con DATEADD para algunas configuraciones regionales.
Mostrar las dificultades de usar una conversión implícita de un literal de cadena
En el siguiente ejemplo se muestra lo que ocurre 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, marzo para el mes.
Evitar resultados erróneos convirtiendo explícitamente el 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
Las dos instrucciones SELECT devuelven marzo para el mes.
Usar 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