【问题标题】:SQL Server: datediff function resulted in an overflow when using MILLISECONDSQL Server:使用 MILLISECOND 时 datediff 函数导致溢出
【发布时间】:2014-11-04 07:56:56
【问题描述】:

我有以下疑问:

select CONVERT(varchar(12), DATEADD(MILLISECOND, DateDiff(MILLISECOND, '2014-08-04 10:37:28.713','2014-11-04 08:21:17.723'), 0), 114)

当我执行这个时,我得到了错误: “datediff 函数导致溢出。分隔两个日期/时间实例的 datepart 数量太大。请尝试使用 datediff 和不太精确的 datepart。”

当我将查询更改为以下内容时,它可以正常工作:

select CONVERT(varchar(12), DATEADD(SECOND, DateDiff(SECOND, '2014-08-04 10:37:28.713','2014-11-04 08:21:17.723'), 0), 114)

问题是我真的也需要 MILLISECONDS。

【问题讨论】:

  • DATEDIFF 返回一个整数,它根本不足以容纳结果。我能想到的唯一方法是计算两个日期之间有多少天,然后仅对两个日期的时间部分进行比较,以计算出相差多少毫秒,然后将两者相加(将天数乘以一天中的毫秒数)。
  • 旁注:您是否在实行某种夏令时的地区工作?因为在很多地方,在您正在查看的期间,DST 的开/关之间存在转换,SQL Server 不会考虑它。因此,您最终可能会得到一个“精确”到毫秒但相差一小时的结果。
  • @Damien_The_Unbeliever 这就是为什么您应该在数据库记录级别规范化日期信息,并在呈现时适当地转换为用户的区域设置。

标签: sql-server sql-server-2012 date-difference


【解决方案1】:

稍后回复,但可能会有所帮助。 在 SQL 2016 中,MS 引入了函数 DATEDIFF_BIG,它将(根据类型大小)溢出大于 29 万年之类的差异。但是technet文章与基本的DATEDIFF具有相同的时差-https://msdn.microsoft.com/en-us/library/mt628058.aspx

【讨论】:

  • 太棒了,我在 2016 年不知道这个新增功能。我们开始使用它有点早,但很高兴知道它即将推出 :)
【解决方案2】:

https://docs.microsoft.com/en-us/sql/t-sql/functions/datediff-transact-sql?view=sql-server-ver15#return-value

对于 毫秒startdateenddate 之间的最大差值为 24 天 20 小时 31 分钟 23.647 秒。

如果您需要高于该级别的毫秒数,则需要编写一些自定义内容。

【讨论】:

    【解决方案3】:

    在 SQL Server 2016 中提供了一个新功能:DATEDIFF_BIG

    正好解决了溢出问题。

    【讨论】:

      【解决方案4】:

      您不需要在计算中参考毫秒数。

      除了溢出之外,这将与您的脚本完全相同:

      SELECT CONVERT(varchar(12), 
              CAST('2014-11-04 08:21:17.723' as datetime) - 
              CAST('2014-08-04 10:37:28.713' as datetime)
             , 114)
      

      【讨论】:

        【解决方案5】:

        对我来说,两个日期之间有很大的间隔,所以我使用了下面的代码

        声明@timetagInMillsecond bigint=CAST(CAST( cast(@timetag as datetime) -'1970-01-01' AS 十进制(38,10))*24*60*60*1000+0.5 as 大整数)

        它对我有用。

        【讨论】:

          【解决方案6】:

          使用 DATEDIFF_BIG 解决溢出问题

          datediff 函数导致溢出。分隔两个日期/时间实例的日期部分的数量太大。尝试将 datediff 与不太精确的日期部分一起使用。

          SELECT DATEDIFF_BIG( 
              millisecond, 
              SYSDATETIME(), 
              DATEADD(year, 1000, SYSDATETIME()) ) AS 'Milliseconds in 1000 years'; 
          

          【讨论】:

            【解决方案7】:

            对于 SQL Server 2014,以下工作围绕“int”限制获取“JavaScript 时间纪元”。这假设开始时期本身就是一个日期,它适合导致找到这个问题的本地用例。查询需要适应不具有此属性的特定问题用例。

            declare @x as datetime = getdate()
            
            -- epoch_delta_s_to_date * 1000 + day_delta_ms
            select
            cast(datediff(second, '1970-01-01', cast(@x as date)) as bigint) * 1000
              + cast(datediff(millisecond, cast(@x as date), @x) as bigint)
            

            对于获取“JavaScript 时间纪元”的情况,这仍然受制于 datediff(second, '1970-01-01', ..) 的 Y2038 限制。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2022-11-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多