【问题标题】:Arithmetic overflow error: Msg 8115, Level 16, State 2算术溢出错误:消息 8115,级别 16,状态 2
【发布时间】:2020-11-11 15:01:47
【问题描述】:

我遇到了一个存储过程的问题,导致:

将表达式转换为数据类型 int 时出现算术溢出错误。

这是两个表,第一个从 ODBC 连接中提取数据。数据包含活动及其开始时间。有一个每天运行的存储过程将这些开始时间转换为间隔。这在绝大多数情况下都有效,但去年有大约十几天由于算术溢出错误而失败。我试图将数据类型从 INT 更改为 Numeric,但这并没有解决问题。非常感谢任何帮助/想法/想法!

存储过程:

insert into [DB].[dbo].[Final_Table]
([resourceName]
      ,[eventdatetime]
      ,[EV2]
      ,[IntervalTime]
      ,[event])

(
SELECT DS1.[resourceName]
      ,DS2.[eventdatetime]
      ,DS1.[eventdatetime] as EV2
      ,CONVERT(varchar(8), DATEADD(ms, DATEDIFF(SECOND, DS2.[eventdatetime], DS1.[eventdatetime]) * 1000, 0), 114) AS [IntervalTime]
      ,DS2.[event]
FROM [DB].[dbo].[Staging_Table] DS1

INNER JOIN [DB].[dbo].[Staging_Table] DS2
    ON DS1.[resourceName] = DS2.[resourceName]
    AND DS1.[ID] = DS2.[ID] + 1)

暂存表:

CREATE TABLE [dbo].[Staging_Table](
    [ID] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
    [resourceName] [varchar](50) NULL,
    [eventdatetime] [datetime] NULL,
    [event] [varchar](9) NULL,
PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

暂存表中的数据:

决赛桌:

CREATE TABLE [dbo].[Final_Table](
    [resourceName] [varchar](50) NULL,
    [eventdatetime] [datetime] NULL,
    [EV2] [datetime] NULL,
    [IntervalTime] [varchar](8) NULL,
    [event] [varchar](9) NULL
) ON [PRIMARY]
GO

决赛桌数据:

【问题讨论】:

  • 谢谢,我已经更新了帖子。显然我一直盯着屏幕太久了。

标签: sql sql-server tsql datediff dateadd


【解决方案1】:

DATEDIFF 函数返回 INT。然后你将它乘以 1000,以毫秒为单位获得秒数的结果。

但是,有时这可能会导致overflow。例如:

DECLARE @A DATETIME2 = '2000-01-01'
       ,@B DATETIME2 = '2001-01-01'


SELECT DATEDIFF(SECOND, @A, @B) * 1000

消息 8115,级别 16,状态 2,第 5 行算术溢出错误 将表达式转换为数据类型 int。

所以,请先转换为BIGINT

DECLARE @A DATETIME2 = '2000-01-01'
       ,@B DATETIME2 = '2001-01-01'


SELECT CAST(DATEDIFF(SECOND, @A, @B) AS BIGINT) * 1000

其实以上方法并不能解决你的问题,因为如果你检查DATEADD函数:

number 参数不能超出 int 的范围。在下面的 语句,number 的参数超出 int 的范围 1。 这些语句都返回以下错误消息:“消息 8115, 第 16 级,状态 2,第 1 行。算术溢出错误转换 将表达式转换为数据类型 int。”

这意味着即使您将 BIGINT 值传递给它(在转换之后),您也会继续收到此错误:

DECLARE @C BIGINT = 31622400000    
SELECT DATEADD(MILLISECOND,  @C  , 0)

您需要以不同的方式处理这种情况。例如,如果您的差异超过INT,则设置MAX 值。

DECLARE @A DATETIME2 = '2000-01-01'
       ,@B DATETIME2 = '2001-01-01'

SELECT TRY_CAST(CAST(DATEDIFF(SECOND, @A, @B) AS BIGINT) * 1000 AS INT)

【讨论】:

  • 可能DATEDIFF_BIG() 是更好的选择(DECLARE @A DATETIME2 = '1900-01-01', @B DATETIME2 = '2001-01-01'返回错误)。
  • @Zhorov 将再次面临DATEADD的限制。
  • 是的,你是对的,DATEADD() 期望 int。但答案是一个可能的解决方案,+1。
猜你喜欢
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 2016-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多