DATEADD (Transact-SQL)

适用于: SQL Server Azure 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

向其中DATEADD添加 int 数字日期部分。 此表列出了所有有效的 datepart 参数 。

注意

对于 datepart 参数,DATEADD 不接受用户定义的变量等效项。

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

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

date

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

  • date
  • datetime
  • datetimeoffset
  • datetime2
  • smalldatetime
  • time

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

返回类型

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

返回值

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 的范围。 以下语句均返回以下错误消息:Msg 8115, Level 16, State 2, Line 1. Arithmetic overflow error converting expression to data type int.

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

date 参数

DATEADD不接受日期参数递增到其数据类型范围之外的值。 在以下语句中,与 date 值相加的 number 值超出了 date 数据类型的范围 。 DATEADD 返回以下错误消息:Msg 517, Level 16, State 1, Line 1 Adding a value to a 'datetime' column caused overflow.

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

返回 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 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 不允许添加时区偏移量。

示例

A. 以 1 为增量递增 datepart

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

DECLARE @datetime2 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. 在一条语句中将 datepart 递增一级以上

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

DECLARE @datetime2 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 INT = 365,
    @datetime 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

此示例使用数值表达式()、一元运算符-(10 / 2)-)、算术运算符/)和标量系统函数(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