在Microsoft SQL Server的类型系统中,使用 date 表示日期类型,使用time表示时间类型,使用DateTime和DateTime2表示日期和时间的组合,DateTime2是DateTime的升级版本,这些数据类型占用的存储空间各不相同;当存储大量数据时,合理的选择小数秒的精度,可以节省数据的占用空间。sql
当表示国际时间时,存在本地时间和UTC时间之别,同一个时刻,UTC时间是固定的,而本地时间因为时区的差别而不相同。若是一个数据实体的时间字段对时区敏感,那么能够使用DateTimeOffset数据类型,该类型不只包含本地的日期和时间,还包括本地的时区,用户可以根据本地的时间和时区推算出UTC时间,公式是:UTC时间=本地时间+时区偏移。express
小数秒的精度(fractional seconds precision)是指使用多少位小数表示一秒,DateTime二、Time和DataTimeOffset能够控制小数秒的精度,语法是DateTime2(n)、time(n),DataTimeOffset(n),n是小数秒的精度,n的取值范围是0-7,默认值是7,即便用7位小数表示1s,可以表示的最小精确时间(Accuracy)是100ns。DateTime数据类型的最小精确时间是3.33毫秒(0.00333秒),其精确度不高,建议在产品环境中,使用DateTime2(n)来代替DateTime类型。函数
DateTime2(n)表示日期和时间,Date只表示日期,Time(n)只表示时间,最后简单介绍DateTime类型。spa
1,DateTime2数据类型code
DateTime2(n)数据类型存储日期和时间,它是DateTime的升级版本,因为小数秒n的精度能够自主设置,其存储大小(Storage Size)不固定,DateTime2(n)占用的存储空间和小数秒的精度之间的关系是:server
DateTime2能够表示比DateTime更精确的时间,默认的数据格式是yyyy-MM-dd hh:mm:ss.nnnnnnn,DateTime2 秒默认的精度是7,即用7位小数表示一秒的精度。blog
datetime2 [ (fractional seconds precision) ]
下面两种声明DateTime2变量的方式是等价的:ci
declare @dt2 datetime2(7) declare @dt2 datetime2
为DateTime2类型的变量赋值,须要使用SysDateTime()和SysUTCDateTime(),这两个函数返回值的类型是DateTime2(7)。rem
declare @dt2 datetime2 set @dt2=SYSDATETIME()
3,Date数据类型文档
Date数据类型只存储日期,不存储时间,仅须要3B的存储空间,默认的数据格式是yyyy-MM-dd,支持的日期范围从0001-01-01到9999-12-31
能够使用日期字符串,getdate()等函数为Date类型的变量赋值:
declare @d date set @d='2015-07-02' set @d=getdate() set @d=SYSDATETIME()
4,Time类型
Time(n)数据类型只存储时间,不存储日期,须要5B的存储空间。Time(n)小数秒精度n的默认值是7,默认的数据格式是hh:mm:ss.nnnnnnn:
time [ (fractional second precision) ]
推荐使用时间字符串和sysdatetime()函数为Time类型的变量赋值,不推荐使用GetDate()函数,GetDate()函数返回的是DateTime类型,时间部分的小数位精度是3,若是对时间的精度要求高,请使用时间字符串和sysdatetime()函数为Time类型的变量赋值。
--declare @t time(7) DECLARE @t time set @t='13:48:43.2840467' set @t=SYSDATETIME() --not recommend set @t=GETDATE()
4,DateTime数据类型
DateTime数据类型存储日期和时间,其存储空间是固定的8个字节,默认的数据格式是yyyy-MM-dd hh:mm:ss.nnn,表示从1753年1月1日到9999年12月31日的日期和时间数据,精确度为3.33毫秒(0.00333秒),也就是说,DateTime表示的日期范围从公元1753年1月1日00:00:00.000 到9999年12月31日23:59:59.997 ,精确到3.33毫秒。
在DateTime使用的8个字节中,实际上,SQL Server用两个4 字节的整数内部存储 datetime 数据类型的值。第一个 4 字节存储基础日期(即 1900 年 1 月 1 日)以前或以后的天数。基础日期是系统参考日期,不容许出现早于 1753 年 1 月 1 日的 date 值。当第一个4 字节为0 时,表示的日期是1900 年1 月1 日;在基础日期以前的日期,第一个4字节的值是负数,在基础日期以后的日期,第一个4字节的值是正数。另一个 4 字节存储以10/3 毫秒数所表明的天天的时间。
declare @dt datetime
使用GetDate()和GetUTCDate()为DateTime类型的变量赋值,这两个函数返回值的类型是DateTime
declare @dt datetime set @dt=getdate()
鉴于DateTime的秒精确度(精确度为3)没有DateTime2(n)高,而且占用的存储空间也比DateTime2(n)高,因此,建议在产品环境中使用DateTime2(n)来代替DateTime类型。
DateTimeOffset(n)数据类型由三部分构成:date、time和 offset(时区偏移),包含了日期、时间和时区数据,其日期和时间使用是本地时间。在本地时间的基础上,使用时区偏移量(offset)来计算UTC时间,所以,DateTimeOffset(n)能够同时表示本地时间和UTC时间,默认的显示文本是:YYYY-MM-DD hh:mm:ss[.nnnnnnn] [{+|-}hh:mm],默认值是1900-01-01 00:00:00 00:00。
DateTimeOffset(n)可以表示的日期、时间和时区范围是:
小数秒的精度会影响变量占用的存储空间的大小:
时区偏移的格式为:[+|-] hh:mm,hh 表示的小时范围是00-14,mm 表示的分钟范围是00-59,把DateTimeOffset时间中的UTC时间 和 时区偏移量 进行算术运算,能够获得本地时间。
1,返回本地时间的DateTimeOffset
返回本地的时间和时区,本地时间是2018-08-29 11:11:29.5765832,本地所在的时区是东八区:
SELECT SYSDATETIMEOFFSET ( )
2,把DateTime2时间转换为DateTimeOffset时间
向DateTime2时间中添加时区信息:
TODATETIMEOFFSET ( expression , time_zone )
参数注释:
例如,使用SYSDATETIME获得本地的DateTime2,添加时区(东八区),获得的包含时区信息的DateTimeOffset:
SELECT TODATETIMEOFFSET(SYSDATETIME(),'+08:00'),SYSDATETIMEOFFSET()
3,切换时区
把DateTimeOffset类型的数据切换到指定的时区,在转换过程当中,UTC时间是固定的,依据固定的UTC时间,切换到特定时区的本地时间:
SWITCHOFFSET ( DATETIMEOFFSET, time_zone )
参数注释:
例如,把本地时间的时区东八区切换到东七区:
DECLARE @remote DATETIMEOFFSET DECLARE @local DATETIMEOFFSET SET @local = SYSDATETIMEOFFSET() SET @remote = SWITCHOFFSET (@local, '+07:00') SELECT @remote AS remote_time,@local AS local_time
能够看到,东7区的时间比东8区的时间晚一个小时。
4,丢弃时区信息
DateTime2表示的是本地时间,DateTimeOffset表示的是本地时间和本地的时区,若是数据不须要考虑时区信息,那么能够直接把DateTimeOffset时间赋值给DateTime2时,SQL Server执行隐式转换,把时区信息丢弃,只把本地时间赋值给DateTime2:
DECLARE @datetimeoffset DATETIMEOFFSET(4) DECLARE @datetime2 DATETIME2(3)=@datetimeoffset; SET @datetimeoffset= '2012-10-25 12:24:32.1277 +01:00' SET @datetime2=@datetimeoffset SELECT @datetimeoffset AS '@datetimeoffset', @datetime2 AS '@datetime2';
DataLength能过返回任意数据类型的变量所占用的字节数量,从下图中能够看到,datetime占用的存储空间太大,精度不高,datetime2完胜datetime,在产品环境中,推荐使用datetime2:
declare @dt1 datetime declare @dt2 datetime2(2) declare @dt3 datetime2(4) set @dt1=getdate() set @dt2=getdate() set @dt3=SYSDATETIME() select DATALENGTH(@dt1),DATALENGTH(@dt2),DATALENGTH(@dt3),@dt1,@dt2,@dt3
若是对time的要求不是很高,保留2位毫秒,使用datetime2(2),比其余类型节省存储空间。
本地时间:世界的每一个地区都有本身的本地时间,整个地球分为二十四时区,每一个时区都有本身的本地时间。
UTC时间:在国际无线电通讯中,为统一而广泛使用一个标准时间,称为通用协调时(UTC, Universal Time Coordinated)。UTC时间和英国伦敦的本地时间相同。UTC时间在世界各地都是相同的,可是不一样的时区,本地时间各不相同。根据UTC时间和所在的时区,可以计算出本地时间。
1,获取本地时间和UTC时间
在SQL Sever中,GetDate()返回的是本地时间,GetUTCDate()返回的是UTC时间,返回的数据类型是DateTime;SysDateTime() 返回的是本地时间,SysUTCDateTime() 返回的是UTC时间,返回的数据类型是DateTime2(7)。
在不一样的时区,UTC时间相同,可是本地时间不一样。本地时间是Server上显示的系统时间,在OS中变动时区(time zone),可以修改本地时间和GetDate()的返回值。本地时间是根据UTC时间和OS设置的时区推导出来的。
结论:GetDate() 和SysDateTime() 返回的是本地Server的Date和Time,这个值跟SQL Server实例本地主机的OS有关,跟OS显示的时间是相同的。
2,SQL Agent 执行Job的时间
在SQL Server Agent中使用的时间是本地时间,Job的执行时间是本地时间。
参考文档: