PostgreSQL中EXTRACT(YEAR FROM date)需确保date为DATE或TIMESTAMP类型,字符串须先转类型如col::DATE;时区、索引及函数使用需注意。

EXTRACT(YEAR FROM date) 在 PostgreSQL 里怎么写才不报错
PostgreSQL 中 EXTRACT 是标准写法,但必须配合 TIMESTAMP 或 DATE 类型字段,不能直接对字符串用。常见错误是传入 '2023-05-12' 这种文本而没转类型。
- 正确姿势:先用
CAST(col AS DATE)或col::DATE转类型,再EXTRACT(YEAR FROM col::DATE) - 如果字段是
TIMESTAMP WITH TIME ZONE,EXTRACT默认按服务器时区算年份,跨时区业务要小心 -
EXTRACT(MONTH FROM ...)返回的是 1–12 的整数,不是字符串,别指望它自动补零 - 性能上,对未索引的日期字段做
EXTRACT会强制全表扫描,查得勤就考虑加函数索引:CREATE INDEX idx_orders_year ON orders ((EXTRACT(YEAR FROM order_date)))
MySQL 用 YEAR() 和 MONTH() 函数要注意什么
MySQL 不支持标准 EXTRACT(8.0+ 才加,但日常还是用原生函数多),YEAR() 看似简单,其实坑在隐式类型转换上。
- 字段是
VARCHAR存的日期(比如'2023/05/12'),YEAR(col)会尝试解析,但遇到'2023-13-01'这种非法值就返回0,不报错也不警告 -
MONTH()对NULL返回NULL,但对空字符串''会返回0,和YEAR()行为不一致 - 想取“2023-05”这种格式,别拼字符串,用
DATE_FORMAT(col, '%Y-%m')更稳;CONCAT(YEAR(col), '-', MONTH(col))遇到月份=5 会变成'2023-5',少个零
SQLite 怎么从 date 字段里拿年份——没有 EXTRACT 也能干
SQLite 没 EXTRACT,也没 YEAR(),靠 strftime() 字符串截取,但得确认你的 date 是标准格式。
- 字段存的是
'2023-05-12'或'2023-05-12 14:30:00':用strftime('%Y', date_col)拿年份,strftime('%m', date_col)拿月份(带前导零) - 如果 date 是 Unix 时间戳(整数秒),得先转:
strftime('%Y', datetime(date_col, 'unixepoch')) - 注意
strftime对非法日期静默失败,比如'2023-02-30'会返回NULL,查出来为空得回头验数据质量
WHERE 条件里用年份过滤,为什么索引失效了
不管用 EXTRACT(YEAR FROM created_at) = 2023 还是 YEAR(created_at) = 2023,数据库大概率没法走索引——因为函数包裹了字段。
- 真正高效的做法是范围查询:
created_at >= '2023-01-01' AND created_at - 如果只能用函数,PostgreSQL 可建表达式索引,MySQL 8.0+ 支持函数索引,SQLite 支持
CREATE INDEX ... ON tbl (strftime('%Y', date_col)) - 别在 WHERE 里写
YEAR(str_to_date(col, '%d/%m/%Y')) = 2023这种嵌套,解析开销大,还彻底放弃索引
日期函数看着简单,但类型、格式、索引这三块最容易漏掉验证。尤其是字段类型和实际存储内容不一致时,EXTRACT 或 YEAR() 会默默给你一个“合理但错误”的结果。










