添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

T-SQL - 在处理毫秒时出现算术溢出

0 人关注

我有一个非常简单的TSQL脚本, 试图 将一个以毫秒为单位的时间戳转换为 DATETIME 数据类型。这也包括当地的时间偏移。

DECLARE @Time AS BIGINT
SET @Time = 1413381394000 
SELECT DATEADD(MILLISECOND, 
               @Time - DATEDIFF(MILLISECOND, GETDATE(), GETUTCDATE()), CAST('1970-01-01 00:00:00' AS DATETIME)) AS [Datetime]

它一直给我的错误是。

Arithmetic overflow error converting expression to data type int.

现在,我在这个查询中没有任何明确的 int 变量,而且我所做的任何CAST()BIGINTDECIMAL(13,0) ,都导致了同样的错误。

在这个查询中,哪个部分是错误的?intDATEDIFF() 的默认返回数据类型吗?

我知道我可以用@Time 除以1000,然后用SECONDS 而不是MILLISECONDS ,我只想知道是否有办法直接用毫秒来工作,因为我的想法是把这个脚本作为一个内联表值函数来使用(在这个查询之外不能用标量函数)。

1 个评论
这是因为DATEADD的第二个参数是一个int,而你传递给它的数值远远大于int。
sql
sql-server
sql-server-2008
mordack550
mordack550
发布于 2014-11-18
3 个回答
JamieSee
JamieSee
发布于 2014-11-18
已采纳
0 人赞同

由于夏令时的原因,你对本地偏移的计算有可能错了一个小时。 DATEDIFF(MILLISECOND, GETDATE(), GETUTCDATE()) ,只能得到当前的偏移,而不是给定日期的偏移。由于SQL缺乏这方面的功能,UTC和当地时间的转换通常最好在应用程序或SQLCLR代码中处理。请看 我如何为一个在夏令时之前或之后的日期获得UTC和当地时间之间的正确偏移?

DATEADD(Transact-SQL) 中,微软指出。

是一个表达式,可以被解析为一个int,被添加到 到日期的一个部分。用户定义的变量是有效的。

If you specify a value with a decimal fraction, the fraction is
truncated and not rounded.

因此,你不能直接处理大于int的最大值的毫秒值,int支持的范围是-2^31(-2,147,483,648)到2^31-1(2,147,483,647),如int, bigint, smallint, and tinyint (Transact-SQL)中所述。你要做的是单独的日期加法和一些模数除法。

DECLARE @Time bigint
DECLARE @Seconds int
DECLARE @RemainingMilliseconds int
DECLARE @EpochDate datetime
SET @Time = 1413381394000
SET @EpochDate = '1970-01-01 00:00:00'
SET @Seconds = @Time / 1000
SET @RemainingMilliseconds = @Time % 1000
SELECT DATEADD(MILLISECOND, @RemainingMilliseconds, DATEADD(SECOND,@Seconds, @EpochDate))
    
p.campbell
p.campbell
发布于 2014-11-18
0 人赞同

DateDiff() 确实返回一个int,但我怀疑是 DateAdd() 给你的错误信息。

你需要在这个精度下工作,不幸的是,你说你想避免,因为你想在毫秒内工作。

DATEADD (datepart , number , date )

number 是一个可以解析为一个int的表达式,它被添加到日期的datepart中。用户定义的变量是有效的。

显然,你可以用循环或其他方式来编码,但显然,你需要考虑成本/效益问题。

Malganis
Malganis
发布于 2014-11-18
0 人赞同

DATEADD的第二个参数应该是INT而不是BIGINT。转换为秒,然后传递给date add。

DECLARE @Time AS BIGINT
SET @Time = 1413381394000 
DECLARE @seconds AS INT = @Time / 1000
SELECT DATEADD(SECOND, @seconds, ...)