SQL Server传入相同起止日期查询返回空表问题排查
问题产生原因
- 表中
BirthDate字段是datetime类型,存储值同时包含日期、时分秒、毫秒部分,你插入的测试数据实际存储的都是2022-06-13当天8点到12点之间的时间点,不是当天零点的时间值。 - 当传入的起止日期为同一天(如
2022-06-13)时,参数隐式转换为datetime类型后的值为2022-06-13 00:00:00.000,也就是当天的零点起始时刻。 - 常规错误写法用
BETWEEN或者<=做结束时间判断时,判断阈值就是当天零点,所有当天零点之后的记录都不满足条件,因此查询返回空表。
错误写法示例
以下是导致同日期查询为空的典型错误SQL:
-- 错误1:BETWEEN 对带时分秒的时间类型判断逻辑不符合预期 SELECT * FROM [dbo].[tblNames] WHERE BirthDate BETWEEN '2022-06-13' AND '2022-06-13' -- 错误2:结束边界直接用传入日期做<=判断,未覆盖当天所有时段 SELECT * FROM [dbo].[tblNames] WHERE BirthDate >= '2022-06-13' AND BirthDate <= '2022-06-13'
以上两种写法执行时,日期字符串会被隐式转换为2022-06-13 00:00:00.000,仅当BirthDate值恰好为当天零点整时才会被匹配,自然查不到你插入的8点~12点的测试数据。
正确查询写法
推荐使用左闭右开的区间判断逻辑,结束时间自动偏移到传入截止日期的下一天零点,既能覆盖截止日期当天所有时段的数据,也能利用BirthDate字段上的索引,不会出现性能问题:
-- 传入参数示例,实际场景替换为你的入参即可 DECLARE @FromDate DATE = '2022-06-13' DECLARE @ToDate DATE = '2022-06-13' SELECT * FROM [dbo].[tblNames] WHERE BirthDate >= @FromDate AND BirthDate < DATEADD(DAY, 1, @ToDate)
执行以上SQL时,结束判断阈值为2022-06-14 00:00:00.000,所有6月13日0点到6月14日0点前的记录(也就是6月13日全天的数据)都会被正确匹配,你插入的4条测试数据可以全部正常返回。
注意:不要使用
CONVERT(DATE, BirthDate) BETWEEN @FromDate AND @ToDate这类对字段做函数转换的写法,这种写法会导致字段上的索引失效,数据量较大时查询性能会非常差。
内容的提问来源于stack exchange,提问作者Jose
相关产品推荐
相关产品推荐

