FORMAT函数在SQL Server 2016中默认不走索引、性能差、大小写敏感;日期格式必须用小写yyyy(日历年),大写YYYY为周所属年易致年份错误;月份用MM、日用dd,mm是分钟,DD非法;WHERE中禁用FORMAT,应改用范围查询。

FORMAT 函数在 SQL Server 2016 中完全可用,但默认不走索引、性能弱、大小写敏感——别直接套用网上搜来的 'YYYY-MM-DD',那大概率输出错年份。
FORMAT 的日期格式字符串必须小写 yyyy,大写 YYYY 是陷阱
SQL Server 的 FORMAT 函数使用 .NET 风格格式字符串,yyyy 和 YYYY 完全不同:yyyy 表示日历年(正确),YYYY 表示“周所属年”(week year),在跨年周(如 2025-12-29 是 ISO 周 2026 年第 1 周)会返回错误年份。
- ✅ 正确写法:
FORMAT(GETDATE(), 'yyyy-MM-dd')→'2026-10-14' - ❌ 错误写法:
FORMAT(GETDATE(), 'YYYY-MM-dd')→ 在 2026 年 1 月第一周可能输出'2027-01-03' - 月份和日也同理:必须用
MM(补零两位月)、dd(补零两位日),mm是分钟,DD不合法
不要在 WHERE 或 JOIN 中用 FORMAT 做条件匹配
FORMAT 返回 nvarchar,且无法下推到索引扫描。一旦写成 WHERE FORMAT(OrderDate, 'yyyy-MM') = '2026-09',SQL Server 就得对整列逐行调用函数,哪怕 OrderDate 上有索引也完全失效。
- ✅ 替代做法:用范围查询
WHERE OrderDate >= '2026-09-01' AND OrderDate - ✅ 若必须字符串比对(如报表参数传入),先在应用层或 CTE 中算好格式化值,再 JOIN
- ⚠️ 注意:
FORMAT(NULL, 'yyyy-MM-dd')返回NULL,不报错,容易让空值逻辑静默失效
文化参数 culture 不填时依赖会话设置,跨环境易出错
省略第三个参数时,FORMAT 会读取当前会话的 LANGUAGE 或 DATEFORMAT 设置。同一句 FORMAT(GETDATE(), 'd') 在 us_english 下是 '10/14/2026',在 German 下是 '14.10.2026',部署到新服务器若没显式设语言,结果就变了。
- ✅ 显式指定:
FORMAT(GETDATE(), 'yyyy-MM-dd', 'en-US')或更稳妥的'en-GB'(ISO 兼容) - ✅ 对纯 ISO 标准输出,直接用
'o'(Round-trip 格式):FORMAT(GETDATE(), 'o')→'2026-10-14T01:25:00.0000000',带毫秒与时区信息(如果输入是DATETIMEOFFSET) - ⚠️
'en-CN'等中文文化下,'D'(长日期)会输出“2026年10月14日 星期三”,但'yyyy-MM-dd'仍安全,不受文化影响
FORMAT vs CONVERT:什么时候该换回 CONVERT
FORMAT 灵活但慢,CONVERT 快但样式固定。SQL Server 2016 中,若只需标准格式(如 yyyy-MM-dd、MM/dd/yyyy),CONVERT 仍是更稳的选择,尤其在视图、函数或高频查询中。
- ✅ 同样效果,更快:
CONVERT(varchar(10), GETDATE(), 120)(注意:120 输出含时间,要截断需LEFT(..., 10)或CONVERT(varchar(10), GETDATE(), 120)) - ✅ 更紧凑的纯日期:
CONVERT(char(10), GETDATE(), 126)→'2026-10-14'(126 是 ISO8601 无时间版) - ⚠️
FORMAT在大数据量聚合中(如百万行 GROUP BY FORMAT(date, 'yyyy-MM'))可能比CONVERT慢 3–5 倍,且内存压力明显上升
真正麻烦的不是语法写不对,而是把 FORMAT 当成万能胶用在不该它出现的地方——比如索引字段上做转换、跨库迁移前没检查兼容性、或者以为 'YYYY' 和 'yyyy' 只是大小写区别。

















