SQL Server更新触发器中无自定义函数实现日期加30工作日
实现方案
不需要创建自定义函数,直接用内联日期计算逻辑即可嵌入UPDATE触发器使用,计算过程仅排除周六、周日,不受会话级@@DATEFIRST配置影响,不会出现星期计算偏差,性能远高于循环、关联日历表的写法,不会影响表写入效率。
核心逻辑
- 30个工作日等价于6个完整工作周,基础自然日偏移为42天
- 先修正原始日期的周末偏移:如果原始日期是周六,延后2天到周一作为计算起点;如果是周日,延后1天到周一作为计算起点
- 加上基础偏移后做最后兜底校验:如果计算结果落在周六,回退1天到周五;落在周日则回退2天到周五,保证最终结果一定是工作日
触发器完整代码
将代码中YourTable替换为实际表名,你的主键列替换为表的实际主键字段名即可直接使用:
CREATE TRIGGER trg_SetAlteredDate ON YourTable AFTER INSERT, UPDATE AS BEGIN SET NOCOUNT ON; -- 仅当Date列发生变更、或插入新数据时才触发计算 IF NOT UPDATE([Date]) AND NOT EXISTS (SELECT 1 FROM inserted) RETURN UPDATE t SET [altered Date] = DATEADD( DAY, -- 最终结果兜底调整,确保落在工作日 CASE ((DATEPART(WEEKDAY, c.calc_base) + @@DATEFIRST - 2) % 7) + 1 WHEN 6 THEN -1 -- 结果为周六,回退到周五 WHEN 7 THEN -2 -- 结果为周日,回退到周五 ELSE 0 END, c.calc_base ) FROM YourTable t INNER JOIN ( SELECT i.你的主键列, calc_base = DATEADD( DAY, 42 + -- 起始日期周末修正 CASE ((DATEPART(WEEKDAY, i.[Date]) + @@DATEFIRST - 2) % 7) + 1 WHEN 6 THEN 2 -- 起始日为周六,跳到周一 WHEN 7 THEN 1 -- 起始日为周日,跳到周一 ELSE 0 END, i.[Date] ) FROM inserted i ) c ON t.你的主键列 = c.你的主键列 END
自定义调整说明
- 如果你的业务规则是不算Date列当天,从次日开始计算30个工作日,把代码里的基础偏移值
42改成41即可,兜底逻辑会自动修正结果到工作日 - 如果后续需要调整增加的工作日天数,只要是5的整数倍,直接把
42替换为(工作日数/5)*7即可;如果不是5的整数倍,只需要在基础偏移上增加零头工作日的周末跨天判断即可
快速验证脚本
不需要建表,直接运行下面的脚本可以验证不同起始日期的计算结果:
SELECT 测试日期 = test_date, 原始星期 = DATENAME(WEEKDAY, test_date), 计算结果 = DATEADD( DAY, CASE ((DATEPART(WEEKDAY, calc_base) + @@DATEFIRST - 2) % 7) + 1 WHEN 6 THEN -1 WHEN 7 THEN -2 ELSE 0 END, calc_base ), 结果星期 = DATENAME(WEEKDAY, DATEADD( DAY, CASE ((DATEPART(WEEKDAY, calc_base) + @@DATEFIRST - 2) % 7) + 1 WHEN 6 THEN -1 WHEN 7 THEN -2 ELSE 0 END, calc_base )) FROM ( VALUES (CAST('2024-06-03' AS DATE)), -- 周一 (CAST('2024-06-07' AS DATE)), -- 周五 (CAST('2024-06-08' AS DATE)), -- 周六 (CAST('2024-06-09' AS DATE)) -- 周日 ) AS test_dates(test_date) CROSS APPLY ( SELECT calc_base = DATEADD( DAY, 42 + CASE ((DATEPART(WEEKDAY, test_date) + @@DATEFIRST - 2) % 7) + 1 WHEN 6 THEN 2 WHEN 7 THEN 1 ELSE 0 END, test_date ) ) cb
内容的提问来源于stack exchange,提问作者Pcube
相关产品推荐
相关产品推荐

