Microsoft SQL Server:整数存储日期的WHERE子句转换报错问题
问题解决方法
报错原因
直接将整数类型的chinto(存储格式为YYYYMMDD)转换为datetime时,SQL Server会把该整数当作从1900-01-01开始的累计天数处理。而20240520这类数值远超出datetime类型的最大允许范围(对应最大天数为2958465,对应日期9999-12-31),因此触发算术溢出错误。
正确的转换与筛选方案
方案1:先转字符串再转日期(兼容所有SQL Server版本)
先将整数转换为8位字符串,再解析为日期类型,同时用TRY_CONVERT自动过滤无效日期值:
AND TRY_CONVERT(DATETIME, CONVERT(VARCHAR(8), h.chinto)) >= DATEADD(DAY, -30, GETDATE())
若需要主动排除非有效日期的数值(比如chinto为0或长度不足8位),可额外添加范围判断:
AND h.chinto BETWEEN 17530101 AND 99991231 -- 限定datetime支持的有效日期范围 AND TRY_CONVERT(DATETIME, CONVERT(VARCHAR(8), h.chinto)) >= DATEADD(DAY, -30, GETDATE())
方案2:使用DATEFROMPARTS函数(SQL Server 2012及以上版本)
拆分整数中的年、月、日部分,直接构造日期,效率更高且逻辑更清晰:
AND DATEFROMPARTS( h.chinto / 10000, -- 提取年份(前4位) (h.chinto / 100) % 100, -- 提取月份(中间2位) h.chinto % 100 -- 提取日期(后2位) ) >= DATEADD(DAY, -30, GETDATE())
同样可先过滤无效数值避免异常:
AND h.chinto BETWEEN 17530101 AND 99991231 AND DATEFROMPARTS(h.chinto/10000, (h.chinto/100)%100, h.chinto%100) >= DATEADD(DAY, -30, GETDATE())
完整修改后的WHERE子句示例
以方案2为例,修改后的WHERE部分代码:
WHERE h.chgpno = 'CTT0001' AND h.chinto BETWEEN 17530101 AND 99991231 AND DATEFROMPARTS(h.chinto/10000, (h.chinto/100)%100, h.chinto%100) >= DATEADD(DAY, -30, GETDATE())
额外排查:找出无效数据
如果仍有报错,说明表中存在不符合YYYYMMDD格式的chinto值,可先查询定位这些数据:
SELECT chinto FROM ACO.dbo.clmhdr WHERE chinto < 17530101 OR chinto > 99991231 OR (chinto % 100) > 31 -- 日期大于31 OR ((chinto / 100) % 100) > 12 -- 月份大于12
内容的提问来源于stack exchange,提问作者Mistymanor
相关产品推荐
相关产品推荐

