DATEADD (Transact-SQL)

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例Azure Synapse Analytics分析平台系统 (PDW)Microsoft Fabric 中的 SQL 分析端点Microsoft Fabric 中的仓库

此函数将数​​字(有符号整数)添加到输入日期的日期部分,并返回修改后的日期/时间值 。 例如,可以使用此函数查找从今天开始的 7,000 分钟日期:number = 7000,datepart = minute,date = today。

有关所有 Transact-SQL 日期和时间数据类型和函数的概述,请参阅 日期和时间数据类型和函数

Transact-SQL 语法约定

语法

DATEADD (datepart , number , date )

参数

datepart

向其中添加 int DATEADD 数字日期部分。

注意

在 Azure SQL 数据库中,Microsoft Fabric 中的 Azure SQL 托管实例和 SQL 数据库, 数字 可以表示为 bigint。 此功能处于预览状态。

此表列出了所有有效的 datepart 参数 。 对于 datepart 参数,DATEADD 不接受用户定义的变量等效项。

datepart 缩写形式
year yyyyyy
quarter qqq
month mmm
dayofyear dyy
day ddd
week wkww
weekday dww
hour hh
minute min
second sss
millisecond ms
microsecond mcs
nanosecond ns

数字

一个表达式,可解析为 将其与 date 的 datepart 相加的 DATEADD 。 对于 number,DATEADD 接受 用户定义的变量值 。 DATEADD 会截断带小数部分的指定 number 值。 在这种情况下,它不会对数字值进行舍入

注意

在 Microsoft Fabric 中的 Azure SQL 数据库和 SQL 数据库中, 数字 可以表示为 bigint。 此功能处于预览状态。

日期

可解析为下列值之一的表达式:

  • 日期
  • 日期/时间
  • datetimeoffset
  • datetime2
  • smalldatetime
  • 时间

对于 日期DATEADD 接受列表达式、表达式、字符串文本或用户定义的变量。 字符串文字值必须解析为 datetime 。 使用四位数年份可避免含糊不清问题。 有关两位数年份的信息 ,请参阅服务器配置:两位数年份截止

返回类型

此方法的返回值数据类型是动态的。 返回类型取决于为 date 提供的参数。 如果 date 的值是字符串文本日期,则 DATEADD 返回日期/时间值 。 如果为 date 提供了其他的有效输入数据类型,则 DATEADD 返回相同的数据类型。 DATEADD 如果字符串文本秒刻度超过三个小数位位置(.nnn)或字符串文本包含时区偏移部分,则引发错误。

返回值

datepart 参数

dayofyeardayweekday 返回相同的值。

每个 datepart 及其缩写都返回相同的值 。

如果以下各项为 true:

  • datepartmonth
  • date 月份比返回月份的天数多
  • 返回 月份中不存在日期 日期

DATEADD 则返回返回月份的最后一天。 例如,9 月有 30 天 (30) 天;因此,这些语句返回 2024-09-30 00:00:00.000

SELECT DATEADD(month, 1, '20240830');
SELECT DATEADD(month, 1, '2024-08-31');

number 参数

number 参数不能超过 int 的范围。在以下语句中,数字的参数超过了 int1 的范围。

SELECT DATEADD(year, 2147483648, '20240731');
SELECT DATEADD(year, -2147483649, '20240731');

这些语句都返回以下错误消息:

Msg 8115, Level 16, State 2, Line 1. Arithmetic overflow error converting expression to data type int.

注意

在 Microsoft Fabric 中的 Azure SQL 数据库和 SQL 数据库中, 数字 可以表示为 bigint。 此功能处于预览状态。

date 参数

DATEADD不接受日期参数递增到其数据类型范围之外的值。 在以下语句中,与 date 值相加的 number 值超出了 date 数据类型的范围 。

SELECT DATEADD(year, 2147483647, '20240731');
SELECT DATEADD(year, -2147483647, '20240731');

DATEADD 返回以下错误消息:

Msg 517, Level 16, State 1, Line 1 Adding a value to a 'datetime' column caused overflow.

返回 smalldatetime 日期和秒或小数秒日期部分的值

smalldatetime 值的秒数部分始终为 00。 以下原则适用于 smalldatetime date 值

  • 对于日期部分second,以及介于 -30 和 +29 之间的数字值,DATEADD不进行更改。

  • second,以及小于 -30 或大于 +29 的数字值,DATEADD从一分钟开始执行其加法。

  • 对于日期部分millisecond和介于 -30001 和 +29998 之间的数字值,DATEADD不进行更改。

  • 对于日期部分millisecond小于 -30001 或大于 +29998 的数字值,DATEADD从一分钟开始执行其添加。

注解

在以下子句中使用 DATEADD

  • GROUP BY
  • HAVING
  • ORDER BY
  • SELECT <list>
  • WHERE

秒的小数部分精度

DATEADD不允许添加microsecondnanosecond日期数据类型 smalldatetimedatedatetime

毫秒的刻度为 3(.123),微秒的刻度为 6(.123456),纳米秒的刻度为 9(.123456789)。 时间、datetime2datetimeoffset 数据类型的最大刻度为 7 ()。 .1234567 nanosecond数字必须为 100,才能在日期增加的小数秒之前。 介于 1 和 49 之间的数字 向下舍入到 0,数字从 50 到 99 舍入到 100。

这些语句添加日期部分millisecondmicrosecondnanosecond

DECLARE @datetime2 AS DATETIME2 = '2024-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);

结果集如下。

1 millisecond     2024-01-01 13:10:10.1121111
2 milliseconds    2024-01-01 13:10:10.1131111
1 microsecond     2024-01-01 13:10:10.1111121
2 microseconds    2024-01-01 13:10:10.1111131
49 nanoseconds    2024-01-01 13:10:10.1111111
50 nanoseconds    2024-01-01 13:10:10.1111112
150 nanoseconds   2024-01-01 13:10:10.1111113

时区偏移量

DATEADD 不允许添加时区偏移量。

示例

答: 以 1 为增量递增 datepart

以下每条语句以 1 为增量递增 datepart :

DECLARE @datetime2 AS DATETIME2 = '2024-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         2025-01-01 13:10:10.1111111
quarter      2024-04-01 13:10:10.1111111
month        2024-02-01 13:10:10.1111111
dayofyear    2024-01-02 13:10:10.1111111
day          2024-01-02 13:10:10.1111111
week         2024-01-08 13:10:10.1111111
weekday      2024-01-02 13:10:10.1111111
hour         2024-01-01 14:10:10.1111111
minute       2024-01-01 13:11:10.1111111
second       2024-01-01 13:10:11.1111111
millisecond  2024-01-01 13:10:10.1121111
microsecond  2024-01-01 13:10:10.1111121
nanosecond   2024-01-01 13:10:10.1111111

B. 在一个语句中递增多个 日期部分 级别

以下每个语句按足够大的 number 逐量增加 datepart,该 number 还应足以增加 date 的下一个更高的 datepart :

DECLARE @datetime2 AS DATETIME2;

SET @datetime2 = '2024-01-01 01:01:01.1111111';

--Statement                                 Result
-------------------------------------------------------------------
SELECT DATEADD(quarter, 4, @datetime2);     --2025-01-01 01:01:01.1111111
SELECT DATEADD(month, 13, @datetime2);      --2025-02-01 01:01:01.1111111
SELECT DATEADD(dayofyear, 366, @datetime2); --2025-01-01 01:01:01.1111111
SELECT DATEADD(day, 366, @datetime2);       --2025-01-01 01:01:01.1111111
SELECT DATEADD(week, 5, @datetime2);        --2024-02-05 01:01:01.1111111
SELECT DATEADD(weekday, 31, @datetime2);    --2024-02-01 01:01:01.1111111
SELECT DATEADD(hour, 23, @datetime2);       --2024-01-02 00:01:01.1111111
SELECT DATEADD(minute, 59, @datetime2);     --2024-01-01 02:00:01.1111111
SELECT DATEADD(second, 59, @datetime2);     --2024-01-01 01:02:00.1111111
SELECT DATEADD(millisecond, 1, @datetime2); --2024-01-01 01:01:01.1121111

°C 使用表达式作为 number 和 date 形参的实参

以下示例使用不同类型的表达式作为 number 和 date 形参的实参 。 示例使用 AdventureWorks 数据库。

将一列指定为 date

此示例将 2 天加到 OrderDate 列中的每个值,以便派生名为 PromisedShipDate 的新列:

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

下面是部分结果集:

SalesOrderID OrderDate               PromisedShipDate
------------ ----------------------- -----------------------
43659        2005-07-01 00:00:00.000 2005-07-03 00:00:00.000
43660        2005-07-01 00:00:00.000 2005-07-03 00:00:00.000
43661        2005-07-01 00:00:00.000 2005-07-03 00:00:00.000
...
43702        2005-07-02 00:00:00.000 2005-07-04 00:00:00.000
43703        2005-07-02 00:00:00.000 2005-07-04 00:00:00.000
43704        2005-07-02 00:00:00.000 2005-07-04 00:00:00.000
43705        2005-07-02 00:00:00.000 2005-07-04 00:00:00.000
43706        2005-07-03 00:00:00.000 2005-07-05 00:00:00.000
...
43711        2005-07-04 00:00:00.000 2005-07-06 00:00:00.000
43712        2005-07-04 00:00:00.000 2005-07-06 00:00:00.000
...
43740        2005-07-11 00:00:00.000 2005-07-13 00:00:00.000
43741        2005-07-12 00:00:00.000 2005-07-14 00:00:00.000

将用户定义的变量指定为 number 和 date

此示例将用户定义的变量指定为 number 和 date 的参数 :

DECLARE
    @days AS INT = 365,
    @datetime AS DATETIME = '2000-01-01 01:01:01.111'; /* 2000 was a leap year */

SELECT DATEADD(day, @days, @datetime);

结果集如下。

2000-12-31 01:01:01.110

将标量系统函数指定为 date

此示例指定 SYSDATETIME 为 date 。 返回的确切值取决于语句执行的日期和时间:

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

结果集如下。

2024-04-25 14:29:59.6727944

将标量子查询和标量函数指定为 number 和 date

此示例使用标量子查询 MAX(ModifiedDate) 作为 number 和 date 的参数 。 (SELECT TOP 1 BusinessEntityID FROM Person.Person) 充当 number 形参的假实参,用来说明如何从值列表中选择 number 实参 。

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

将数值表达式和标量系统函数指定为 number 和 date

此示例使用数值表达式()、一元运算符-算术运算符/)和标量系统函数(SYSDATETIME)作为数字日期的参数

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

将排名函数指定为 number

此示例使用排名函数作为 number 的参数 。

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 的参数 。

SELECT SalesOrderID,
       ProductID,
       OrderQty,
       DATEADD(day, SUM(OrderQty) OVER (PARTITION BY SalesOrderID), SYSDATETIME()) AS 'Total'
FROM Sales.SalesOrderDetail
WHERE SalesOrderID IN (43659, 43664);
GO