Sql server 在SQL Server 2016(AWS)中将表达式转换为数据类型int时出现算术溢出错误

Sql server 在SQL Server 2016(AWS)中将表达式转换为数据类型int时出现算术溢出错误,sql-server,amazon-web-services,Sql Server,Amazon Web Services,我们使用的是AWS的许可版本SQL Server Standard 2008 R2。我们正在将数据库从SQL 2008 R2 10.50.1600.1升级到SQL Server 2016 13.0.16106.4。将兼容性级别设置为130后,下面的查询返回下面的错误 Msg 8115,16级,状态2,第22行算术溢出错误 正在将表达式转换为数据类型int wfWorkflows和wfTasks两个表都有相同的列WorkflowId,数据类型为INT,不为NULL declare @Company

我们使用的是AWS的许可版本SQL Server Standard 2008 R2。我们正在将数据库从SQL 2008 R2 10.50.1600.1升级到SQL Server 2016 13.0.16106.4。将兼容性级别设置为130后,下面的查询返回下面的错误

Msg 8115,16级,状态2,第22行算术溢出错误 正在将表达式转换为数据类型int

wfWorkflows和wfTasks两个表都有相同的列WorkflowId,数据类型为INT,不为NULL

declare @CompanyID int = 510, @RecordPkId int = 4551138,@zoneDifference varchar(6) = null

Select Minutes = 
               (
               Select sum(isnull(TimeSpentOnTask,0)) 
               from wfTasks With(nolock) 
               inner join comAdvisers With(nolock)  on 
               comAdvisers.AdviserId = wfTasks.AdviserId 
               Where WorkflowId = wfWorkflows.WorkflowId
               )
from wfWorkflows With(nolock) 
Where companyid = @CompanyID 
And ISNULL(ClientID,AdviserID) = @RecordPkId And ISNULL(InitSave,0) <> 1;
若我从select中注释任何一列,那个么我将不会得到任何错误,查询工作正常。在所有列中,我都得到了一个错误。 声明@CompanyID int=510、@RecordPkId int=4551138、@zoneDifference varchar6=null

选择分钟=从wfTasks Withnolock中选择sumisnullTimeSpentOnTask,0,其中WorkflowId=WFWorkflowId.WorkflowId, EstMinutes=从wfTasks Withnolock中选择sumisnullDuration,1 其中WorkflowId=wfWorkflows.WorkflowId 从wfWorkflows Withnolock
其中companyid=@companyid和ISNULLClientID,advisionRid=@RecordPkId和ISNULLInitSave,0 1

即使所有内容都是int,总和也会溢出int类型,这很正常,请看以下内容:

    declare @t table(col int);
    insert into @t values(2147483647),(2147483647);

    select sum(col)
    from @t;

    --Msg 8115, Level 16, State 2, Line 4
    --Arithmetic overflow error converting expression to data type int.

    select sum(cast(col as bigint))
    from @t;
在我的第一次选择中,我得到了错误,这是正确的,因为结果不适合int。在我的第二次选择中,我将每个summand强制转换为bigint,因此总和也将是bigint,并且不会发生溢出

因此,作为第一步,您应该将summand强制转换为bigint,以至少接收结果,并查看它是否能有效地适应int。如果不能,则早期版本也不能,这是数据的问题。如果结果足够小,可以放入int,原因可能如下:如果有负和,则计算和的顺序是meters,例如,如果我有

2147483647 - 2147483647 + 2 
我仍然适合int,但如果我按照以下顺序进行操作会发生什么:

2147483647 + 2 - 2147483647
它在第一步溢出int。
因此,在您的案例中可能发生的情况是,例如,parralel计划以不同的方式重新划分输入,因此总体结果仍然可以适合int,但其中一个流导致int溢出

在不知道是什么数据导致问题的情况下,如何回答?不要查找bug,在导致问题的子查询中查找不适合intwhere条件的值。如果我将第一列强制转换为bigint,那么它将被解析。其中castWorkflowId为bigint=wfWorkflowId.WorkflowId。我们有大约4000 Db的组件,将所有列转换为bigint不是可行的解决方案。使用NOLOCK意味着您可以读取脏数据。这意味着不尊重锁,而不是不接受锁。这表明您的查询已经存在性能问题。简化你的查询,注释部分,然后一个接一个地返回,直到你发现是哪一个导致了超负荷。那么为什么要问一个问题呢?如果数字太大,则表示该数字太大。这正是错误所说的:在视图之间切换,使用外部筛选聚合子查询,NOLOCK,我想说您已经有很多问题要解决了。特别是如果您有太多的行,TimePentonTask之和需要64位整数I有超过4000 DB的组件,转换为BIGINT不是可行的解决方案。我没有告诉您更改数据类型,您可以在聚合时强制转换它,仅在查询中,为了接收结果并查看它是否适合int。来自帖子的查询不包含4000个组件,使用cast as bigint重写它需要1分钟