当前位置:首页 > 问答 > 正文

带你随便看看Sql Server里那些格式化时间用的函数到底是咋回事儿

微软官方SQL Server技术文档T-SQL参考——日期和时间函数部分,以及《SQL Server编程入门经典》中对日期处理函数的应用讲解)

咱今天就唠唠SQL Server里那些花里胡哨的格式化时间函数,你可能在代码里见过CONVERT,也听说过FORMAT,但它们到底有啥不一样?用哪个才不踩坑?咱们就随便看看,把它们的老底儿都翻出来。

老牌劲旅:CONVERT函数

(来源:T-SQL参考手册)CONVERT这函数,可以说是SQL Server里的老资格了,它最主要的特点就是,因为它干这事儿已经干了很多年了,数据库引擎对它优化得门儿清。

它的基本写法长这样: CONVERT(数据类型, 要转换的表达式 [, 样式代码]) 格式化时间的关键,就在那个可选的“样式代码”上,这个样式代码就是个数字,不同的数字代表不同的日期显示格式。

举个例子,你数据库里存了个日期‘2023-10-27’,它是个标准的日期类型,但你想把它变成中国人习惯的‘2023年10月27日’这种样子,或者变成‘10/27/2023’这种美国格式。

这时候CONVERT就派上用场了:

  • 你用 CONVERT(VARCHAR, GETDATE(), 111),它给你返回‘2023/10/27’。
  • 你用 CONVERT(VARCHAR, GETDATE(), 112),它给你返回‘20231027’(纯数字,一天都不带差的)。
  • 你想用横杠?CONVERT(VARCHAR, GETDATE(), 23) 给你‘2023-10-27’。

(来源:《SQL Server编程入门经典》中的建议)书上说,CONVERT的优点是效率高,特别是在处理海量数据的时候,你能明显感觉到它比后面要讲的那位快得多,但它的缺点也很明显:你得死记硬背那些样式代码,比如120样式是‘yyyy-mm-dd hh:mi:ss’,121样式多了个毫秒……除非你天天用,否则根本记不住,每次都得查文档。

带你随便看看Sql Server里那些格式化时间用的函数到底是咋回事儿

新派花旦:FORMAT函数

(来源:T-SQL参考手册)FORMAT函数是SQL Server 2012版本才加进来的“新家伙”,它的出现,简直就是程序员的福音,因为它用的是我们更熟悉的.NET框架里的格式化字符串

它的写法是: FORMAT(要转换的值, 格式字符串 [, 区域文化选项]) 这家伙的强大之处在于,格式字符串非常直观!你不用记代码,直接用字母表示就行。

  • 你想得到‘2023年10月27日’,直接写 FORMAT(GETDATE(), 'yyyy年MM月dd日'),看,是不是一目了然?
  • 你想得到‘Friday, October 27, 2023’,写 FORMAT(GETDATE(), 'dddd, MMMM dd, yyyy') 就行。
  • 你甚至可以玩出花来:FORMAT(GETDATE(), 'yyyy-MM-dd HH:mm:ss'),这里的HH代表24小时制,要是用小写hh就是12小时制。

(来源:微软官方博客关于FORMAT函数性能的说明)凡事都有但是,FORMAT虽然写起来爽,看起来明白,但它有个致命的弱点:,因为它底层是调用.NET的CLR(公共语言运行时)来处理的,这个开销比原生C写的CONVERT函数大得多,如果你的数据量很大,比如要对一个有几百万行的表里的日期字段进行格式化,用FORMAT可能会导致查询速度急剧下降,所以有句老话叫“FORMAT虽好,可不要贪杯哦”,用在大量数据查询时要特别小心。

他俩到底咋选?简单总结一下

带你随便看看Sql Server里那些格式化时间用的函数到底是咋回事儿

(来源:综合社区最佳实践和性能测试结论)

  1. 追求速度,处理大数据量:二话不说,用CONVERT,哪怕去查一下样式代码表,也比用FORMAT让数据库干等着强。
  2. 追求代码清晰易懂,格式复杂多变,或者数据量很小:比如你就格式化一下当前时间显示在报表标题上,用FORMAT,代码好写又好维护,别人一看就知道你想干嘛。
  3. 需要依赖特定区域设置:FORMAT的第三个参数可以指定文化区域,比如FORMAT(GETDATE(), 'D', 'zh-CN')会自动输出中文长日期格式,这是CONVERT做不到的。

除了这俩,还有别的招吗?

(来源:T-SQL参考手册——字符串函数部分) 当然有!有时候最简单的办法反而是最有效的,对于一些超级简单的格式化,你甚至不用劳驾上面两位。

你只想得到‘20231027’这个字符串,除了用CONVERT的112样式,你还可以用最原始的字符串拼接: SELECT CAST(YEAR(GETDATE()) AS VARCHAR) + RIGHT('0' + CAST(MONTH(GETDATE()) AS VARCHAR), 2) + RIGHT('0' + CAST(DAY(GETDATE()) AS VARCHAR), 2) 虽然写起来啰嗦,但在某些极端追求性能的场景下,这种原始方法可能比函数调用还要快那么一丢丢。

最后唠叨一句 (来源:DBA经验之谈)说白了,在数据库里,日期时间最好就一直用原生的DATETIME、DATE这些类型存着、算着。格式化输出这件事,应该尽量放到最后一步,甚至放到你的应用程序(比如C#、Java代码)或者报表工具里去做的。 让数据库专心做它擅长的数据存储和计算,把打扮显示样式的活儿交给前端,这样整个系统的效率才是最高的。

这些格式化函数就像是工具箱里的不同工具,CONVERT是把结实耐用的锤子,FORMAT是把功能齐全的瑞士军刀,没有谁最好,关键看你要钉钉子还是开罐头,了解了它们的内幕,你用起来心里就有谱了。