MySQL中YEAR()、MONTH()、DAY()可直接提取日期字段的年、月、日部分,适用于DATE/DATETIME/TIMESTAMP类型;字符串需先用STR_TO_DATE()转换,否则格式不标准时返回NULL。

MySQL里用YEAR()、MONTH()、DAY()直接取值
MySQL提供了最直白的日期部件提取函数,不需要字符串拆分或类型转换。只要字段是DATE、DATETIME或TIMESTAMP类型,就能直接用:
SELECT YEAR(order_date) AS y, MONTH(order_date) AS m, DAY(order_date) AS d FROM orders;注意
DAY()返回的是「当月第几天」(1–31),不是「星期几」;要取星期用WEEKDAY()或DAYOFWEEK()。如果字段是字符串(比如'2023-04-15'),MySQL通常能自动转换,但遇到格式不标准(如'15/04/2023')就会返回NULL,得先用STR_TO_DATE()转成日期类型。
PostgreSQL必须用EXTRACT(),语法和参数名都不同
PostgreSQL不支持YEAR()这类函数,统一用EXTRACT(),而且字段名要加引号、单位名是小写关键字:
SELECT EXTRACT(YEAR FROM order_date) AS y, EXTRACT(MONTH FROM order_date) AS m, EXTRACT(DAY FROM order_date) AS d FROM orders;常见错误是写成
EXTRACT(year FROM ...)(小写)——其实可以,但推荐大写保持可读性;更关键的是,如果order_date是TEXT类型,会报错function extract(unknown, text) does not exist,必须显式转类型:order_date::DATE或CAST(order_date AS DATE)。
SQL Server别用DATEPART()拼字符串,小心时区和边界
DATEPART()是SQL Server的标准方式,但容易被误用于构造日期字符串(比如DATEPART(YEAR, dt) + '-' + DATEPART(MONTH, dt)),这会触发隐式转换失败(int + string)。正确做法是单独提取:
SELECT DATEPART(YEAR, order_date) AS y, DATEPART(MONTH, order_date) AS m, DATEPART(DAY, order_date) AS d FROM orders;另外要注意:SQL Server的
DATEPART(WEEKDAY, ...)默认把周日当第一天(值为1),如果业务按周一为起点,得提前设置SET DATEFIRST 1,否则结果会偏移。
跨数据库兼容写法?别硬凑,优先选目标库原生函数
有人想写个“通用SQL”用strftime()或SUBSTRING()硬解析'2023-04-15',但这只在字段固定为YYYY-MM-DD格式时才安全。一旦数据里混入'2023/04/15'、'15-APR-2023'或TIMESTAMP带时分秒,就全崩了。真正需要多库兼容的场景(比如ORM生成SQL),应该让应用层根据方言动态切换函数名,而不是在SQL里塞一堆CASE WHEN判断数据库类型。毕竟日期解析逻辑越靠近存储层,越容易失控。

















