Joh*_*han 1 sql sql-server arithmetic-overflow
我收到此错误,但仅在按特定列分组时出现:
Arithmetic overflow error converting expression to data type int.
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么。这是导致它的查询(总和函数是罪魁祸首):
SELECT a.AtgardAvvattningId,
a.ObjektId,
sum(p.SlutLopLangd - p.StartLopLangd) As TotalLangd
FROM AtgardAvvattning a
INNER JOIN Objekt o ON o.ObjektId = a.ObjektId
INNER JOIN Position p ON p.AvvattningAtgardId = a.AtgardAvvattningId
INNER JOIN Vna v ON v.PositionId = p.PositionId
WHERE v.OID IN (...)
GROUP BY a.AtgardAvvattningId, a.ObjektId, o.AtgardsDatum
ORDER BY a.ObjektId
Run Code Online (Sandbox Code Playgroud)
p.SlutLopLangd 和 p.StartLopLangd 都是 int 列。如果我在求和之前将值转换为 bigint,它会起作用:
sum(CONVERT(bigint, p.SlutLopLangd - p.StartLopLangd)) As TotalLangd
Run Code Online (Sandbox Code Playgroud)
给出这个结果:
| AtgardAvvattningId | 对象ID | 总面积 |
|---|---|---|
| 直流9... | 9B2... | 25684 |
| 儿童早期发展... | 9B2... | 25700 |
| 3D0... | 9B2... | 170005 |
| 959... | 9B2... | 170005 |
| 商务英语考试... | 214... | 11814 |
| C31... | 214... | 11815 |
正如您所看到的,没有任何总和接近 int 的限制。奇怪的是,如果我像这样在 group by 子句中包含positionId,它不会引发错误:
SELECT a.AtgardAvvattningId,
a.ObjektId,
sum(p.SlutLopLangd - p.StartLopLangd) As TotalLangd
FROM AtgardAvvattning a
INNER JOIN Objekt o ON o.ObjektId = a.ObjektId
INNER JOIN Position p ON p.AvvattningAtgardId = a.AtgardAvvattningId
INNER JOIN Vna v ON v.PositionId = p.PositionId
WHERE v.OID IN (...)
GROUP BY a.AtgardAvvattningId, a.ObjektId, o.AtgardsDatum, p.PositionId
ORDER BY a.ObjektId
Run Code Online (Sandbox Code Playgroud)
在本例中,AtgardAvvattning 和 Position 之间是一对一的关系。此查询给出与上面完全相同的结果。
当值如此小时,为什么它首先会引发算术溢出?为什么它在第二个中起作用?有什么不同?我知道如果没有数据和表结构可能很难给出答案,但任何提示都会有所帮助。
更新:
使用此查询完全删除组时:
SELECT a.AtgardAvvattningId,
a.ObjektId,
p.PositionId,
v.VnaId,
p.StartLopLangd,
p.SlutLopLangd,
p.SlutLopLangd - p.StartLopLangd as Subtraction
FROM AtgardAvvattning a
INNER JOIN Objekt o ON o.ObjektId = a.ObjektId
INNER JOIN Position p ON p.AvvattningAtgardId = a.AtgardAvvattningId
INNER JOIN Vna v WITH (NOLOCK) ON v.PositionId = p.PositionId
WHERE v.OID IN (...)
ORDER BY a.ObjektId
Run Code Online (Sandbox Code Playgroud)
结果根本没有很多行:
| AtgardAvvattningId | 对象ID | 职位编号 | 虚拟现实 | 启动LopLangd | 荡妇LopLangd | 减法 |
|---|---|---|---|---|---|---|
| DC96... | 9B2... | 第473章 | 1345183 | 168501 | 174922 | 6421 |
| ECD4... | 9B2... | 07E... | 1252649 | 74602 | 81027 | 6425 |
| ECD4... | 9B2... | 07E... | 1252651 | 74602 | 81027 | 6425 |
| ECD4... | 9B2... | 07E... | 1252652 | 74602 | 81027 | 6425 |
| ECD4... | 9B2... | 07E... | 1252650 | 74602 | 81027 | 6425 |
| DC96... | 9B2... | 第473章 | 1345180 | 168501 | 174922 | 6421 |
| DC96... | 9B2... | 第473章 | 1345181 | 168501 | 174922 | 6421 |
| DC96... | 9B2... | 第473章 | 1345182 | 168501 | 174922 | 6421 |
| 3D08... | 公元前9年... | F18... | 1374284 | 199000 | 233001 | 34001 |
| 3D08... | 公元前9年... | F18... | 1374283 | 199000 | 233001 | 34001 |
| 9590... | 公元前9年... | A2D... | 1374285 | 16591 | 50592 | 34001 |
| 9590... | 公元前9年... | A2D... | 1374286 | 16591 | 50592 | 34001 |
| 9590... | 公元前9年... | A2D... | 1374287 | 16591 | 50592 | 34001 |
| 9590... | 公元前9年... | A2D... | 1374289 | 16591 | 50592 | 34001 |
| 9590... | 公元前9年... | A2D... | 1374288 | 16591 | 50592 | 34001 |
| 3D08... | 公元前9年... | F18... | 1374281 | 199000 | 233001 | 34001 |
| 3D08... | 公元前9年... | F18... | 1374280 | 199000 | 233001 | 34001 |
| 3D08... | 公元前9年... | F18... | 1374282 | 199000 | 233001 | 34001 |
| C31B... | 214... | B20... | 1349999 | 32756 | 44571 | 11815 |
| BEC3... | 214... | F21... | 1349998 | 205022 | 216836 | 11814 |
无论您如何对行求和,都应该很难达到 int 溢出限制。
最终值实际上并不重要。可能发生的情况是,在您的某个时刻,SUM您超过了 an 的最大值 (2,147,483,647) 或最小值 (-2,147,483,648)int并出现错误。
举个例子:
SELECT SUM(V.I)
FROM (VALUES(2147483646),
(2),
(-2006543543))V(I);
Run Code Online (Sandbox Code Playgroud)
这可能会产生相同的错误:
将表达式转换为数据类型 int 时出现算术溢出错误。
然而,结果SUM将是 140,940,105(远低于最大值)。这是因为如果 2147483646先将和2相加,则得到2147483648,它大于 an 的最大值int。如果您先CAST/CONVERT该值,则不会收到错误:
SELECT SUM(CONVERT(bigint,V.I))
FROM (VALUES(2147483646),
(2),
(-2006543543))V(I);
Run Code Online (Sandbox Code Playgroud)