先看为快
-- 查找 2023-10-01 当天的所有数据
WHERE OrderDate >= '20231001'
AND OrderDate < '20231002';
在 SQL Server 中,与固定日期进行比较时,核心原则是使用标准的日期格式字符串或日期字面量,以确保查询能够正确利用索引(SARGable)并避免隐式转换带来的性能问题或错误。
以下是几种推荐的写法及注意事项:
1. 推荐写法:使用 ISO 8601 格式字符串
这是最安全、最通用的方法,不受服务器语言设置(Language Settings)的影响。
- 格式
YYYYMMDD(无分隔符):适用于纯日期比较。-- 比较 2023年10月1日 WHERE OrderDate >= '20231001' AND OrderDate < '20231002'; - 格式
YYYY-MM-DDThh:mm:ss(带 T 分隔符):适用于包含时间的 datetime/datetime2 类型。-- 比较 2023年10月1日 下午2点30分 WHERE CreatedAt >= '2023-10-01T14:30:00';
2. 使用 DATE 或 DATETIME2 字面量 (SQL Server 2008+)
如果你明确知道列的数据类型,可以直接使用类型前缀,这样代码可读性更高且类型安全。
-- 显式转换为 DATE 类型
WHERE OrderDate >= CAST('2023-10-01' AS DATE)
-- 或者直接使用日期字面量 (SQL Server 会隐式处理,但显式更好)
WHERE OrderDate >= '2023-10-01' -- 如果列是 DATE 类型,这通常也是安全的
3. 常见场景示例
场景 A:查找特定日期的所有记录(注意时间部分)
如果列类型是 DATETIME 或 DATETIME2,它包含时间部分。直接等于某个日期字符串通常查不到数据(除非时间恰好是 00:00:00)。 错误写法:WHERE OrderDate = '2023-10-01' (只会匹配 2023-10-01 00:00:00.000)
正确写法(范围查询):
-- 查找 2023-10-01 当天的所有数据
WHERE OrderDate >= '20231001'
AND OrderDate < '20231002';
这种写法可以利用索引,效率最高。
替代写法(使用 CAST,可能无法利用索引):
-- 将列转换为日期进行比较 (会导致索引失效,大数据量表不推荐)
WHERE CAST(OrderDate AS DATE) = '2023-10-01';
场景 B:查找早于或晚于某日期的记录
-- 查找 2023年1月1日 之前的记录
WHERE ExpiryDate < '20230101';
-- 查找 2023年1月1日 之后的记录(包含当天)
WHERE StartDate >= '20230101';
4. 需要避免的写法
- 避免使用区域性格式:如
'01/10/2023'或'10-01-2023'。- 如果服务器语言设置为
us_english(mdy),'01/10/2023'会被解析为 1月10日。 - 如果服务器语言设置为
British(dmy),'01/10/2023'会被解析为 10月1日。 - 这会导致代码在不同服务器上行为不一致。
- 如果服务器语言设置为
- 避免在列上进行函数运算(除非万不得已):
- 不要写
WHERE YEAR(OrderDate) = 2023 AND MONTH(OrderDate) = 10,这会导致全表扫描。请改用范围查询>= '20231001' AND < '20231101'。
- 不要写
总结最佳实践代码
SELECT *
FROM Orders
WHERE
-- 推荐使用 YYYYMMDD 格式进行日期范围过滤
OrderDate >= '20231001'
AND OrderDate < '20231002'
-- 如果需要精确到时间点,使用 ISO 8601 (带 T)
AND CreatedAt >= '2023-10-01T09:00:00';
这种方式既保证了准确性(不受语言设置影响),又保证了性能(可以使用索引)。
关键词:日期表达式,日期计算


请登录后查看回复内容