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 日期和时间数据类型和函数的概述,请参阅 日期和时间数据类型和函数 。
语法
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 参数
dayofyear
, day
并 weekday
返回相同的值。
每个 datepart 及其缩写都返回相同的值 。
如果以下各项为 true:
- datepart 为
month
- 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 的范围。在以下语句中,数字的参数超过了 int 到 1 的范围。 以下语句均返回以下错误消息: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
不允许添加日期部分microsecond
或nanosecond
日期数据类型 smalldatetime、date 和 datetime。
毫秒的刻度为 3(.123
),微秒的刻度为 6(.123456
),纳米秒的刻度为 9(.123456789
)。 时间、datetime2 和 datetimeoffset 数据类型的最大刻度为 7 (.1234567
)。 对于日期部分nanosecond
,数字必须为 100,才能在日期增加的小数秒之前。 介于 1 和 49 之间的数字 向下舍入到 0,数字从 50 到 99 舍入到 100。
这些语句添加日期部分,millisecond
microsecond
或nanosecond
。
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