• 企业400电话
  • 网络优化推广
  • AI电话机器人
  • 呼叫中心
  • 全 部 栏 目

    网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    SQL Server 日期和时间的内部存储过程
    POST TIME:2021-10-18 17:59

    在SQL Server的内部存储中,日期和时间不是以字符串的形式存储的,而是使用整数来存储的。使用特定的格式来区分日期部分和时间部分的偏移量,并通过基准日期和基准时间来还原真实的数据。

    一,DateTime的内部存储

    SQL Server存储引擎把DateTime类型存储为2个int32类型,共8个字节,第一个int32 整数(前4个字节)存储的是日期相对于基准日期(1900-01-01)的偏移量。基准日期是1900-01-01,当前4 字节为0 时,表示的日期是1900 年1 月1 日。第二个int32整数(后4个字节)存储的是午夜(00:00:00.000)之后的时钟滴答数,每个滴答为1⁄300秒,精确度为3.33毫秒(0.00333秒,3.33ms),因此,DateTime能够表示的时间,可能会存在一个滴答的时间误差。

    DateTime的内部存储格式,用十六进制表示是:DDDDTTTT

    举个例子,对于如下的日期和时间,把DateTime类型转换为大小为8个字节的16进制,每两个数字对应1个字节:

    declare @dt datetime = '2015-05-07 10:05:23.187'
    select convert(varbinary(8), @dt) as date_time_binary
    --output 0x0000A49100A6463C

    1,拆分出date和time

    把时间的二进制格式中的字节拆分成两部分:前4个字节表示date,后4个字节表示time,得出的结果如下:

    declare @dt datetime = '2015-05-07 10:05:23.187'
    
    select substring(convert(varbinary(8), @dt), 1, 4) as date_binary,
     cast(substring(convert(varbinary(8), @dt), 1, 4) as int) as date_int,
     substring(convert(varbinary(8), @dt), 5, 4) as time_binary,
     cast(substring(convert(varbinary(8), @dt), 5, 4) as int) as time_int;

     

    2,通过偏移量还原日期和时间

    通过基准时间和偏移量,把整数还原为原始的日期和时间:

    declare @Time time='00:00:00.000'
    declare @Date date='1900-01-01'
    
    select dateadd(day, 42129, @Date) as originl_date
     , dateadd(ms,10896956*10/3, @Time) as original_time

    二,DateTime2的内部存储

    DateTime2(n)数据类型存储日期和时间,它是DateTime的升级版本,由于小数秒n的精度可以自主设置,其存储大小(Storage Size)不固定,DateTime2(n)占用的存储空间和小数秒的精度之间的关系是:

    1,二进制逆序

    在探索DateTime2(n)的内部存储之前,先了解一下字节存储的“小端”格式和“大端”格式:

    举个例子,假如内存地址左边是地位,右边是高位,对于数字275,使用两个字节来存储:

    DateTime2(n)的内部存储格式使用的是小端格式,这种格式适合CPU的运算。

    2,DateTime2的存储格式

    DateTime2(n)的内部存储格式是:

    TUI是由精度来控制的,每一个TUI是10的n次方之一秒,也就是:

    为了便于运算,把DateTime2(n) 的字节流逆序排列:前3个字节表示的是天数,最后一个字节表示的是精度,中间余下的字节表示的TUI的数量。例如,对于 DateTime2(7)按照字节流逆序处理之后,存储空间是9个字节:前三个字节是存储的从基准日期0001-01-01之后的多少天,最后一位是精度n,中间的5个字节表示从子夜开始有多少个TUI。

    2,把DateTime2转换为二进制存储

    把DateTime2转换为二进制存储,并作逆序处理,DateTime2(3)的精度为3,存储空间是8个字节,后三个字节记录从基准日期0001-01-01之后的多少天,前3个字节表示从子夜开始有多少个TUI。

    declare @dt datetime2(3)='2015-05-07 10:05:23.187'
    declare @dt_bi varbinary(max)=convert(varbinary(max), @dt) 
    select @dt_bi as date_time_binary
     ,convert(varbinary(max),reverse(@dt_bi)) as reverse_binary

    把二进制值拆分成DateTime2(3)的各个组成成分:

    declare @dt datetime2(3)='2015-05-07 10:05:23.187'
    declare @dt_bi varbinary(max)=convert(varbinary(max), @dt) 
    declare @dt_bi_littleEnd varbinary(max)
    select @dt_bi_littleEnd=convert(varbinary(max),reverse(@dt_bi))
    
    select substring(convert(varbinary(8), @dt_bi_littleEnd), 1, 3) as date_binary,
     cast(substring(convert(varbinary(8), @dt_bi_littleEnd), 1, 3) as int) as date_int,
     substring(convert(varbinary(8), @dt_bi_littleEnd), 4, 4) as time_binary,
     cast(substring(convert(varbinary(8), @dt_bi_littleEnd), 4, 4) as int) as time_int,
     substring(convert(varbinary(8), @dt_bi_littleEnd), 8, 1) as precision_binary,
     cast(substring(convert(varbinary(8), @dt_bi_littleEnd), 8, 1) as int) as precision_int;

    3,利用偏移量和基准还原原始值

    有了偏移量,就可以在基准日期和时间之上加上偏移量来获得原始值:

    declare @Time time='00:00:00.000'
    declare @Date date='0001-01-01'
    
    select dateadd(day, 735724, @Date) as originl_date
     , dateadd(ms,36323187, @Time) as original_time


    参考文档:

    What is the SQL Server 2008 DateTime2 Internal Structure?

    How to Get SQL Server Dates and Times Horribly Wrong

    总结

    以上所述是小编给大家介绍的SQL Server 日期和时间的内部存储,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
    如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

    您可能感兴趣的文章:
    • 解析MySQL中存储时间日期类型的选择问题
    • sql server动态存储过程按日期保存数据示例
    • SQL查询出表、存储过程、触发器的创建时间和最后修改时间示例
    • 返回SQL执行时间的存储过程
    上一篇:sql server日志处理不当造成的隐患详解
    下一篇:delete误删数据使用SCN号恢复(推荐)
  • 相关文章
  • 

    关于我们 | 付款方式 | 荣誉资质 | 业务提交 | 代理合作


    © 2016-2020 巨人网络通讯

    时间:9:00-21:00 (节假日不休)

    地址:江苏信息产业基地11号楼四层

    《增值电信业务经营许可证》 苏B2-20120278

    X

    截屏,微信识别二维码

    微信号:veteran88

    (点击微信号复制,添加好友)

     打开微信