extract函数支持提取year、month、day、hour、minute、second等标准字段,部分数据库还支持quarter、week、dow、doy等;返回double precision数值,需显式转换类型;严格要求字段名全大写(postgresql)、源值必须为时间类型而非字符串,并受时区影响。

EXTRACT 能提取哪些日期部分?
SQL 的 EXTRACT 函数支持从 TIMESTAMP、DATE 或带时区的时间值中取出指定字段,常见可提取项包括:YEAR、MONTH、DAY、HOUR、MINUTE、SECOND,部分数据库还支持 QUARTER、WEEK、DOW(周几)等。
注意:EXTRACT 返回的是整数,不是字符串;不同数据库对字段名大小写敏感性不一(PostgreSQL 严格区分,MySQL 和 SQLite 不区分,但推荐全大写以保兼容)。
PostgreSQL / Oracle / Standard SQL 中的写法
标准语法统一为:EXTRACT(field FROM source),其中 field 是要提取的单位,source 是时间表达式。
例如从订单时间取年月日:
SELECT EXTRACT(YEAR FROM order_time) AS y, EXTRACT(MONTH FROM order_time) AS m, EXTRACT(DAY FROM order_time) AS d FROM orders;
常见错误:
-
EXTRACT(YEAR FROM '2023-05-12')在 PostgreSQL 中会报错,因为字符串需先转为DATE或TIMESTAMP,应写成EXTRACT(YEAR FROM '2023-05-12'::DATE) - Oracle 中若源字段是
DATE类型,EXTRACT仍可直接用,但不能提取SECOND(因DATE不含秒),需转为TIMESTAMP
MySQL 和 SQLite 不支持 EXTRACT,怎么办?
MySQL 没有 EXTRACT 函数,得用 YEAR()、MONTH()、DAY() 等专用函数替代:
SELECT YEAR(order_time) AS y, MONTH(order_time) AS m, DAY(order_time) AS d FROM orders;
SQLite 同样不支持 EXTRACT,需用 strftime():
SELECT
strftime('%Y', order_time) AS y,
strftime('%m', order_time) AS m,
strftime('%d', order_time) AS d
FROM orders;
注意:strftime 返回字符串,如需数值类型得套 CAST(... AS INTEGER);且 SQLite 的日期字段必须是合法格式(如 'YYYY-MM-DD' 或 'YYYY-MM-DD HH:MM:SS'),否则返回 NULL。
跨数据库兼容写法难不难?
真要写一次跑多库,基本做不到——函数名、参数顺序、字段关键字(YEAR vs 'year')、空值行为都不同。最现实的做法是:
- 明确目标数据库,按其语法写
- 在应用层(如 Python/Java)做日期解析,避免把逻辑塞进 SQL
- 如果必须 SQL 层统一,可用
CASE WHEN+ 数据库标识变量(如@@version或current_database())动态拼接,但维护成本高,一般只用于中间件或 ORM 封装
真正容易被忽略的点:时区。比如 EXTRACT(HOUR FROM now()) 在 PostgreSQL 中默认按服务器时区算,而 now() AT TIME ZONE 'UTC' 才能确保一致性——年月日看似不受影响,但跨夏令时或时区字段(TIMESTAMPTZ)时,DAY 值可能因本地化偏移差一天。










