EXTRACT是标准SQL函数,需用大写字段名如YEAR且带FROM(PostgreSQL),MySQL不支持而用YEAR()等;YEAR/MONTH函数虽简洁但无法走索引,大数据量应改用范围查询。

EXTRACT 用法和常见错误
EXTRACT 是标准 SQL 函数,跨数据库兼容性好,但参数写法容易出错。它必须搭配 YEAR、MONTH、DAY 等字段标识符使用,不能直接写成 EXTRACT(year FROM date_col) 这种形式——括号里要加引号或关键字,具体看数据库。
常见错误现象:ERROR: function extract(unknown, timestamp without time zone) does not exist,通常是 PostgreSQL 里漏写了 FROM 或用了小写字段名(如 year 而非 YEAR)。
- PostgreSQL:必须写
EXTRACT(YEAR FROM date_col),YEAR大写且不加引号 - MySQL 不支持
EXTRACT的这种语法,会报错;要用YEAR()、MONTH()等函数替代 - BigQuery 支持
EXTRACT(YEAR FROM date_col),也支持EXTRACT(DATE FROM timestamp_col)提取完整日期 - 注意时区影响:如果输入是
TIMESTAMP WITH TIME ZONE,EXTRACT 按会话时区计算,不是 UTC
YEAR/MONTH/DAY 函数在 MySQL 和 SQL Server 中怎么用
这些是 MySQL 和 SQL Server 提供的便捷函数,写起来短,但只在对应数据库生效,换环境就挂。
典型使用场景:快速筛选某年某月的数据,比如查 2023 年 5 月订单,写 WHERE YEAR(order_time) = 2023 AND MONTH(order_time) = 5 很直观,但性能差——无法走索引。
- MySQL 中
YEAR(date_col)返回整数,date_col可以是DATE、DATETIME或TIMESTAMP - SQL Server 也支持
YEAR()、MONTH(),但更推荐DATEPART(yy, date_col),因为后者还能取季度、周、毫秒等 - 所有这类函数都会让 WHERE 条件失效索引,真实表数据量大时,应改用范围查询:
WHERE order_time >= '2023-05-01' AND order_time - SQL Server 的
DAY()和DATEPART(dd, ...)行为一致,但DAY('2023-02-29')在非闰年会报错,而DATEPART不会
跨数据库安全提取年月日的替代方案
想写一次 SQL 跑多个库?别依赖 EXTRACT 或 YEAR(),改用字符串截取或日期格式化函数更稳,前提是字段类型统一为 DATE 或能转成标准格式。
例如把 '2023-05-17' 拆成年、月、日,本质是字符串操作,只要确保输入格式固定,就几乎无兼容问题。
- 通用做法:
SUBSTRING(date_col::TEXT, 1, 4)(PostgreSQL)、SUBSTR(date_col, 1, 4)(MySQL),前提是date_col能隐式转成'YYYY-MM-DD'格式 - BigQuery 用
FORMAT_DATE('%Y', date_col)最稳妥,返回字符串,再配合CAST(... AS INT64)转数字 - 避免用
TO_CHAR(date_col, 'YYYY')(PostgreSQL)或CONVERT(VARCHAR, date_col, 112)(SQL Server),它们格式依赖区域设置,可能在不同服务器上输出不同 - 如果原始字段是
TIMESTAMP或带时分秒,先用DATE(date_col)截断再处理,否则字符串截取可能错位
为什么 DATE_PART 比 EXTRACT 更值得留意(PostgreSQL 场景)
PostgreSQL 里 DATE_PART 和 EXTRACT 功能重叠,但行为细节差异明显,尤其在边界值和单位缩写上。
比如想取“一年中的第几天”,EXTRACT(DOY FROM '2023-01-01'::DATE) 返回 1,而 DATE_PART('doy', ...) 同样返回 1,看起来一样——但 DATE_PART 允许用小写字符串('year'),EXTRACT 必须用大写关键字(YEAR)。
-
DATE_PART('isoyear', now())可取 ISO 周年份,EXTRACT不支持ISOYEAR -
DATE_PART('epoch', timestamp_col)返回秒级时间戳,EXTRACT(EPOCH FROM ...)也能做到,但写法不同 - 对
TIMESTAMP WITH TIME ZONE,DATE_PART('hour', t)返回本地时区小时,EXTRACT(HOUR FROM t)一样,但文档明确说DATE_PART更倾向按会话时区解释 - 实际项目中,如果已用
DATE_PART,没必要为了“标准”硬切到EXTRACT,两者性能无差别,但混用容易记混大小写和引号规则
'2023-02-30')、时区、隐式类型转换的处理都不一样,真正在意可移植性或稳定性时,别省那几行代码——显式 CAST、固定格式字符串、避开函数包装,往往比“写得短”更重要。










