DATE()函数在MySQL、PostgreSQL(14+)、SQLite中可直接提取日期部分,但SQL Server不支持需用CAST/CONVERT,Oracle用TRUNC,BigQuery强制用DATE;为避免索引失效,应改用范围查询而非函数包裹列。

SQL里用DATE()函数提取日期部分最简单
MySQL、PostgreSQL(14+)、SQLite 都支持 DATE() 函数,它直接剥离时间,只保留年月日。注意不是所有数据库都叫这个名字——SQL Server 没有 DATE() 函数,用它会报错 Invalid column name 'DATE'。
常见错误是把 DATE() 当作类型转换函数乱套,比如写成 DATE(CAST(created_at AS DATE)),纯属冗余;只要字段是 DATETIME 或 TIMESTAMP 类型,DATE(created_at) 就够了。
- MySQL:✅ 支持,
WHERE DATE(order_time) = '2024-05-20' - PostgreSQL:✅ 14+ 支持,旧版需用
created_at::DATE - SQLite:✅ 支持,
DATE('now')也行 - SQL Server:❌ 不支持,会提示“无法解析的函数名”
SQL Server 必须用CAST(... AS DATE)或CONVERT(DATE, ...)
SQL Server 的 DATE 是一种独立数据类型,不能当函数用。想截掉时间,得显式类型转换。用 CAST 更标准,CONVERT 多一个风格参数但没必要。
别写 CAST(created_at AS DATETIME) —— 这没变;也别漏掉括号,CAST created_at AS DATE 语法错误,必须带圆括号。
- 正确:
WHERE CAST(order_date AS DATE) = '2024-05-20' - 也行:
WHERE CONVERT(DATE, order_date) = '2024-05-20' - 错误:
CAST order_date AS DATE(缺括号) - 错误:
CAST(order_date AS DATETIME)(没去掉时间)
WHERE条件里对日期列用函数可能让索引失效
无论用 DATE() 还是 CAST,只要在列上套函数,大多数数据库就无法走 order_date 字段上的 B-tree 索引。查询一慢,容易误判成数据量大,其实是执行计划走了全表扫描。
更高效的做法是改写为范围查询,例如把 DATE(order_time) = '2024-05-20' 换成:
WHERE order_time >= '2024-05-20' AND order_time <p>这样能命中索引,尤其在千万级订单表里,响应时间可能从秒级降到毫秒级。</p>
- 适用所有数据库,不依赖函数支持
- 注意右边界用
而非,避免跨天误差 - 如果字段是
TIMESTAMP WITH TIME ZONE,还得考虑时区归一化
Oracle 和 BigQuery 的写法差异容易踩坑
Oracle 没有 DATE() 函数,也不支持 CAST(... AS DATE) 直接去时间——它的 DATE 类型本身就含时间,得用 TRUNC()。BigQuery 则强制要求用 DATE(),且参数必须是 TIMESTAMP,传 STRING 会报 No matching signature for function DATE。
- Oracle:
WHERE TRUNC(order_time) = DATE '2024-05-20'(注意字面量写法) - BigQuery:
WHERE DATE(order_time) = DATE '2024-05-20',若字段是字符串,先用PARSE_TIMESTAMP - 别在 Oracle 里写
CAST(order_time AS DATE)—— 类型没变,时间还在 - BigQuery 中
DATE('2024-05-20')合法,但DATE('2024/05/20')会失败
函数名和类型关键字大小写不敏感,但字符串字面量格式、时区隐含行为、索引友好度这些细节,才是线上查不出数据或查得太慢的真正原因。










