FORMAT函数支持标准格式字符串(如'd'、'D')、自定义模式(如'yyyy-MM-dd'),区分大小写,依赖.NET规则且需合法format和culture参数;返回varchar导致排序/索引失效,性能低于CONVERT,仅建议用于本地化场景。

FORMAT函数在SQL Server里支持哪些日期格式化字符串?
FORMAT 函数依赖 .NET 的格式化规则,不是 SQL Server 原生语法,所以必须传入合法的 format 字符串和 culture(可选)。常见错误是直接套用 MySQL 的 %Y-%m-%d 或 Oracle 的 TO_CHAR 风格,结果报错:Msg 2809, Level 16, State 1: The format parameter is invalid.
- 支持标准格式字符串:如
'd'(短日期)、'D'(长日期)、'f'(完整日期+时间)、'g'(常规日期时间) - 支持自定义模式:如
'yyyy-MM-dd'、'dd/MM/yyyy HH:mm:ss'、'MMM dd, yyyy' - 注意大小写敏感:
'yyyy'是四位年份,'YYYY'会返回空值或意外结果 -
culture参数影响分隔符和星期顺序,比如'en-US'和'zh-CN'对'D'的输出不同
为什么SELECT中用FORMAT后排序/索引失效?
FORMAT 返回的是 varchar 类型,哪怕你只格式化一个 datetime 字段,结果也不能直接参与日期比较或走索引查找。
- 如果写
ORDER BY FORMAT(CreateTime, 'yyyy-MM'),实际按字符串排序:'2023-01' < '2023-10' < '2023-2'(因为字符比较),不是时间逻辑 - 在 WHERE 中用
FORMAT(CreateTime, 'yyyy-MM-dd') = '2024-03-15'会导致全表扫描,无法利用CreateTime上的索引 - 正确做法是:先用原生日期函数过滤(如
WHERE CreateTime >= '2024-03-15' AND CreateTime < '2024-03-16'),再用FORMAT仅做展示层处理
FORMAT在SQL Server 2012+可用,但性能比CONVERT差很多
FORMAT 内部调用 .NET CLR,每次调用都有跨层开销。实测在百万行数据上,FORMAT(col, 'yyyy-MM-dd') 比 CONVERT(varchar(10), col, 120) 慢 3–5 倍。
- 简单转换优先用
CONVERT:如CONVERT(char(10), GetDate(), 120)得到'2024-03-15' - 需要本地化(如中文星期、阿拉伯数字)才考虑
FORMAT,例如FORMAT(GetDate(), 'dddd, MMMM dd, yyyy', 'zh-CN') - 不要在视图或函数里无节制使用
FORMAT,尤其当该对象被频繁 JOIN 或聚合时
遇到NULL或非日期类型字段时FORMAT怎么不报错?
FORMAT 对 NULL 输入返回 NULL,这点安全;但它对非日期类型(比如传入 int 或 varchar)会直接报错:Cannot convert a value of type 'int' to type 'datetime'。
- 必须确保第一参数是
datetime、date、time、datetime2等可格式化类型 - 可加
TRY_CONVERT防御:如FORMAT(TRY_CONVERT(datetime, SomeColumn), 'yyyy-MM-dd') - 如果字段本身是字符串(如 '20240315'),别直接
FORMAT(SomeColumn, ...),先TRY_CONVERT(date, SomeColumn)再格式化
注意:FORMAT 的文化参数不是可有可无的装饰——它决定月份名、星期名、AM/PM 符号甚至数字分隔符,漏掉可能导致生产环境显示异常,尤其是部署在非英文系统时。

















