DAY()函数跨数据库行为不同:MySQL/SQL Server支持,PostgreSQL/Oracle需用EXTRACT(DAY FROM date_col),SQLite用strftime('%d',date_col);返回整数无前导零;文本日期须先转日期类型;WHERE中需防NULL和非法日期。

DAY() 函数在不同数据库中的行为差异
MySQL 和 SQL Server 支持 DAY(),但 PostgreSQL、SQLite、Oracle 不支持这个函数名——直接用会报错 function day() does not exist 或类似提示。PostgreSQL 用 EXTRACT(DAY FROM date_col),SQLite 用 strftime('%d', date_col),Oracle 用 EXTRACT(DAY FROM date_col) 或 TO_CHAR(date_col, 'DD')。
所以别硬套 DAY(),先确认你用的是哪种数据库:
- MySQL / SQL Server:放心用
DAY(date_col) - PostgreSQL / Oracle:改用
EXTRACT(DAY FROM date_col) - SQLite:必须用
strftime('%d', date_col),且确保输入是合法日期字符串(如'2024-03-15')
DAY() 返回值不是字符串,而是整数
很多人误以为 DAY('2024-03-05') 会返回 '05',其实 MySQL 返回的是整数 5 —— 没前导零。这在拼接路径、生成文件名或做条件过滤时容易出错。
如果需要两位数格式(比如 '05'),得手动补零:
- MySQL:
LPAD(DAY(date_col), 2, '0') - PostgreSQL:
TO_CHAR(date_col, 'DD') - SQLite:
strftime('%d', date_col)本身就返回'05'
注意:SQL Server 的 DAY() 同样返回整数,要用 RIGHT('0' + CAST(DAY(date_col) AS VARCHAR(2)), 2) 补零,稍麻烦。
DAY() 不能直接处理字符串型日期字段
如果表里存的是文本,比如 date_str VARCHAR(10) 存着 '2024/03/05' 或 '05-MAR-2024',DAY(date_str) 在 MySQL 里可能“碰巧”成功(依赖隐式转换),但结果不可靠;在 PostgreSQL 或 SQL Server 中基本会报错 invalid input syntax for type date。
安全做法是先转成日期类型再提取天数:
- MySQL:
DAY(STR_TO_DATE(date_str, '%Y-%m-%d'))(需匹配实际格式) - PostgreSQL:
EXTRACT(DAY FROM TO_DATE(date_str, 'YYYY-MM-DD')) - SQL Server:
DAY(CAST(date_str AS DATE))(仅当格式为 ISO 标准如'2024-03-05'才可靠)
格式不一致时,隐式转换失败率很高,尤其遇到 '5/3/2024' 这类模糊写法,数据库可能按美式或欧式解析,结果翻车。
用 DAY() 做 WHERE 条件时要注意 NULL 和非法日期
WHERE DAY(created_at) = 15 看似简单,但若 created_at 是 NULL 或存了 '0000-00-00'(MySQL 允许的非法日期),DAY() 返回 NULL,整行被过滤掉——不是报错,而是静默丢失数据。
排查这类问题时,建议加一层防御:
- 显式排除 NULL:
WHERE created_at IS NOT NULL AND DAY(created_at) = 15 - 过滤非法日期(MySQL):
WHERE created_at != '0000-00-00' AND DAY(created_at) = 15 - PostgreSQL 可结合
IS VALID或用TRY_CAST(某些版本支持),但更稳妥的是提前清洗数据
生产环境里,日期字段没设 NOT NULL 或没加检查约束(CHECK)的话,DAY() 很容易变成“隐形漏斗”,查不到数据却找不到原因。

















