extract支持year、month、day、hour、minute、second等标准字段,postgresql还支持dow、doy,sqlite仅支持前六种且要求iso8601字符串输入,mysql不支持extract而需用year()等函数。

EXTRACT能提取哪些日期字段?
EXTRACT 是标准 SQL 函数,用于从日期/时间值中抽取指定部分。它支持的字段名因数据库而异,但 YEAR、MONTH、DAY 在 PostgreSQL、Oracle、SQL Server(2012+)、SQLite(3.8.6+)中都可用;MySQL 不支持 EXTRACT,得用 YEAR()、MONTH() 等替代函数。
常见错误是写成 EXTRACT(YEAR FROM '2023-05-12') 却在 MySQL 里执行——直接报错 FUNCTION EXTRACT does not exist。
- PostgreSQL / Oracle:支持
YEAR、MONTH、DAY、HOUR、MINUTE、SECOND、DOW(周几,0=Sunday)、DOY(年中第几天) - SQLite:只支持
YEAR、MONTH、DAY、HOUR、MINUTE、SECOND,且要求输入是 ISO8601 格式字符串(如'2023-05-12 14:30:00') - SQL Server:用
DATEPART()更常见,但EXTRACT在较新版本中已兼容(需确认 compatibility level ≥ 150)
怎么写才能跨数据库少踩坑?
不同数据库对输入类型容忍度不同:EXTRACT 在 PostgreSQL 中可直接作用于 DATE、TIMESTAMP,但在 SQLite 中若传入 DATE 类型列(非字符串),会返回 NULL。
- 确保输入是明确的时间类型或合规字符串:PostgreSQL 可自动 cast
'2023-05-12'为 date,SQLite 则要求显式格式 - 避免在 WHERE 条件中对列用
EXTRACT做过滤(如WHERE EXTRACT(YEAR FROM created_at) = 2023),这通常无法走索引,性能差;改用范围查询:created_at >= '2023-01-01' AND created_at - 如果目标库是 MySQL,别硬套
EXTRACT,直接用:YEAR(created_at)、MONTH(created_at)、DAY(created_at)
示例(PostgreSQL):
SELECT EXTRACT(YEAR FROM '2023-05-12'::DATE) AS y, EXTRACT(MONTH FROM '2023-05-12'::DATE) AS m, EXTRACT(DAY FROM '2023-05-12'::DATE) AS d;返回:y=2023, m=5, d=12
为什么有时返回小数或负数?
EXTRACT 对 TIMESTAMP WITH TIME ZONE 的行为依赖时区设置。比如在 PostgreSQL 中:
-
EXTRACT(YEAR FROM TIMESTAMP '2023-01-01 00:00:00+14')可能返回 2022(因时区超前,本地时间仍是前一日) -
EXTRACT(HOUR FROM INTERVAL '2.5 hours')返回2.5,不是整数——EXTRACT对 interval 类型会保留小数部分
容易忽略的点:
-
EXTRACT返回的是DOUBLE PRECISION(PostgreSQL)或NUMERIC(Oracle),不是整数类型,做等值比较时注意隐式转换 -
DOW(星期几)在 PostgreSQL 中是 0–6(Sunday=0),Oracle 是 1–7(Monday=1),结果不一致
时区和数据类型精度是实际迁移或联查时最容易翻车的地方。










