Поделиться через


DATEADD (Transact-SQL)

Возвращает дату, полученную как сумму исходной даты date и интервала number (целое число со знаком), добавленного к заданному компоненту datepart даты date.

Обзор всех типов данных и функций даты и времени в языке Transact-SQL см. в разделе Функции даты и времени (Transact-SQL). Сведения и примеры, относящиеся к типам данным и функциям даты и времени, см. в разделе Использование данных даты и времени.

Значок ссылки на разделСинтаксические обозначения в Transact-SQL

Синтаксис

DATEADD (datepart , number , date )

Аргументы

  • datepart
    Компонент даты date, к которому добавляется интервал integernumber. В следующей таблице перечислены все допустимые аргументы datepart. Эквивалентные переменные, определяемые пользователем, являются недопустимыми.

    datepart

    Сокращения

    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
    Выражение, которое преобразуется к типу int и добавляется к компоненту datepart даты date. Допускаются пользовательские переменные.

    Если указать значения с десятичной дробью, дробь усекается, а не округляется.

  • date
    Выражение, которое можно привести к значению типа time, date, smalldatetime, datetime, datetime2 или datetimeoffset. Параметр date может быть выражением, выражением столбца, определяемой пользователем переменной или строковым литералом. Если выражение является строковым литералом, его результатом должно быть значение типа datetime. Во избежание неоднозначности используйте четырехзначную запись года. Дополнительные сведения о двузначном обозначении года см. в разделе Параметр two digit year cutoff.

Типы возвращаемых данных

Тип возвращаемых данных является типом аргумента date, за исключением строковых литералов.

Тип возвращаемых данных для строкового литерала имеет тип datetime. Если строковый литерал имеет более трех позиций долей секунды (NNN) или содержит компонент смещения часового пояса, возникнет ошибка.

ПримечаниеПримечание

Если для параметра date не выполняется явное приведение строковых литералов, то при использовании DATEADD в сочетании с другими функциями даты-времени в локалях, где действует формат даты «день-месяц-год» (дмг), возможны неверные результаты.

Возвращает тип datetime2

DATEADD возвращает тип datetime2, если параметр date имеет тип datetime2. При использовании строковых литералов для параметра date их необходимо неявно привести к типу datetime2, чтобы DATEADD вернул тип datetime2.

Аргумент datepart

Функции dayofyear, day и weekday возвращают одинаковое значение.

Каждое выражение datepart и его краткие формы возвращают одно и то же значение.

Если datepart имеет тип month, а в месяце даты date имеется больше дней, чем в возвращаемом месяце, и день даты date не существует в этом месяце, возвращается последний день месяца. Например, в сентябре 30 дней, поэтому следующие две инструкции возвращают 2006-09-30 00:00:00.000:

SELECT DATEADD(month, 1, '2006-08-30')

SELECT DATEADD(month, 1, '2006-08-31')

Аргумент number не может выходить за диапазон типа данных int. В следующих инструкциях аргумент number превышает диапазон типа данных int на 1. Выдается следующее сообщение об ошибке: «Арифметическое переполнение при преобразовании выражения к типу данных int».

SELECT DATEADD(year,2147483648, '2006-07-31');
SELECT DATEADD(year,-2147483649, '2006-07-31');

Аргумент date не может быть увеличен до значения, выходящего за диапазон соответствующего типа данных. В следующих инструкциях значение number прибавляется к значению date и в результате превышается диапазон типа данных date. Выдается следующее сообщение об ошибке: «Добавление значения в столбец "datetime" привело к переполнению».

SELECT DATEADD(year,2147483647, '2006-07-31');
SELECT DATEADD(year,-2147483647, '2006-07-31');

Значение секунд даты типа smalldatetime всегда равно 00. Если аргумент date имеет тип smalldatetime, действуют следующие условия.

  • Если datepart имеет значение second и number лежит между -30 и +29, добавление не выполняется.

  • Если datepart имеет значение second и number менее -30 или более +29, выполняется добавление времени, начиная с одной минуты.

  • Если datepart имеет значение millisecond и number лежит между -30001 и +29998, добавление не выполняется.

  • Если datepart имеет значение millisecond и number менее -30001 или более +29998, выполняется добавление времени, начиная с одной минуты.

Замечания

Функция DATEADD может использоваться в предложениях SELECT <список>, WHERE, HAVING, GROUP BY и ORDER BY.

Точность в долях секунды

Использование при сложении в качестве аргумента datepart значений microsecond или nanosecond для типов данных date: smalldatetime, date и datetime не допускается.

Миллисекунды имеют точность 3 знака (0,123), микросекунды имеют точность 6 знаков (0,123456), наносекунды — 9 знаков (0,123456789). Типы данных time, datetime2 и datetimeoffset имеют максимальную точность 7 знаков (0,1234567). Если аргументом datepart является nanosecond, аргумент number должен иметь значение 100 перед увеличением даты date на доли секунды. Значение аргумента number, находящееся в пределах 1 до 49, округляется до 0, а значение от 50 до 99 округляется до 100.

Следующие инструкции добавляют часть даты datepart: millisecond, microsecond или 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
*/

Смещение часового пояса

При смещении часового пояса добавление не допускается.

Примеры

А. Увеличение части даты на интервал, равный 1

Каждая следующая инструкция увеличивает часть даты datepart на интервал, равный 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
*/

Б. Увеличение нескольких уровней части даты в одной инструкции

Каждая следующая инструкция увеличивает часть даты datepart на число number, достаточно большое, чтобы увеличить следующую часть даты datepart даты 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

В. Использование выражений в качестве аргументов number и date

В следующих примерах выражения различного типа используются в качестве аргументов для параметров number и date.

Использование в качестве аргумента date столбца

В следующем примере к каждой дате OrderDate добавляются 2 дня для вычисления новой даты PromisedShipDate.

USE AdventureWorks2008R2;
GO
SELECT SalesOrderID
    ,OrderDate 
    ,DATEADD(day,2,OrderDate) AS PromisedShipDate
FROM Sales.SalesOrderHeader;

Указание пользовательских переменных в качестве аргументов number и date

В следующем примере в качестве аргументов number и 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);

Указание в качестве аргумента date скалярной системной функции

В следующем примере в качестве аргумента date указывается SYSDATETIME.

SELECT DATEADD(month, 1, SYSDATETIME());

Указание в качестве аргументов number и date скалярных вложенных запросов и скалярных функций

В следующем примере скалярные вложенные запросы и скалярные функции, MAX(ModifiedDate) используются в качестве аргументов number и date. (SELECT TOP 1 BusinessEntityID FROM Person.Person) является искусственным аргументом для параметра number, чтобы показать способ выбора аргумента number из списка значений.

USE AdventureWorks2008R2;
GO
SELECT DATEADD(month,(SELECT TOP 1 BusinessEntityID FROM Person.Person),
    (SELECT MAX(ModifiedDate) FROM Person.Person));

Указание констант в качестве аргументов number и date

В следующем примере в качестве аргументов number и date используются числовые и символьные константы.

SELECT DATEADD(minute, 1, '2007-05-07 09:53:01.0376635');

Указание в качестве аргументов number и date числовых выражений и скалярных системных функций

В следующем примере числовые выражения (-(10/2)), унарные операторы (-), арифметический оператор (/) и скалярные системные функции (SYSDATETIME) используются в качестве аргументов number и date.

SELECT DATEADD(month,-(10/2), SYSDATETIME());

Указание в качестве аргумента number ранжирующих функций

В следующем примере ранжирующие функции используются в качестве аргументов 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;

Указание в качестве аргумента number статистической оконной функции

В следующем примере в качестве аргумента 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

Г. Использование DATEADD для локалей, в которых используется формат дат дмг

В следующем примере описывается использование строковых литералов с DATEADD для определенных локалей.

Описание проблем при неявном приведении строковых литералов

В следующем примере показано, что происходит, если не выполняется явное приведение строкового литерала.

SET LANGUAGE Español;

GO

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

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

GO

Первая инструкция SELECT возвращает julio (июль) для месяца, а вторая инструкция SELECT возвращает marzo (март) для месяца.

Исключение ошибочных результатов путем явного приведения строковых литералов

В приведенном ниже примере показано явное приведение параметра date, что позволяет избежать получения неправильных результатов.

SET LANGUAGE Español;

GO

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

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

GO

Обе инструкции SELECT возвращают marzo (март) для месяца.

Использование переменной datetime2 вместо строкового литерала

В следующем примере строковый литерал не используется напрямую.

SET LANGUAGE Español;

GO

DECLARE @d datetime2 = '1987-03-07';

SELECT DATENAME(m, DATEADD(d, 0, @d));

SELECT DATENAME(m, @d);

GO

См. также

Справочник