Sql server 2012 在where子句中使用int变量转换十进制时出现算术溢出错误(错误?)

Sql server 2012 在where子句中使用int变量转换十进制时出现算术溢出错误(错误?),sql-server-2012,Sql Server 2012,我认为这是SQL Server(2012)中的一个奇怪错误,但请帮我检查一下是否正常。这是一个存储过程中丑陋查询的过度简化版本(实际查询有13个表)。表3.r为十进制(12,2) 示例表定义: CREATE TABLE Table1 (bpid int IDENTITY(1, 1), blah int, ...) CREATE TABLE Table2 (elid int IDENTITY(1, 1), blah int, wth int, tid int...) CREATE TABLE Ta

我认为这是SQL Server(2012)中的一个奇怪错误,但请帮我检查一下是否正常。这是一个存储过程中丑陋查询的过度简化版本(实际查询有13个表)。表3.r为十进制(12,2)

示例表定义:

CREATE TABLE Table1 (bpid int IDENTITY(1, 1), blah int, ...)
CREATE TABLE Table2 (elid int IDENTITY(1, 1), blah int, wth int, tid int...)
CREATE TABLE Table3 (..., wth int, tid int, r decimal(12, 2))
表3大约有8万条记录。99.999%的查询时间有效。但至少在一个奇怪的情况下,t3.r=24.79(尽管我不认为24.79本身有问题),它会导致这个错误:

将数值转换为数据类型数值时出现算术溢出错误

然后我发现,如果您只是在WHERE子句中硬编码-1,它就可以正常工作:

....
    AND t3.tid > -1;
SELECT TOP 1 t3.r
...
    AND t3.tid > @tid; -- var is still in the WHERE clause
或者,如果您只是选择t3.r(而不是尝试转换为14,10),它也可以正常工作:

....
    AND t3.tid > -1;
SELECT TOP 1 t3.r
...
    AND t3.tid > @tid; -- var is still in the WHERE clause
或者,如果将@tid设置为只生成一条记录的值(它通常返回3或4条记录,然后获取前1条记录),那么它也可以工作:

SELECT @elid = 123, @bpid = 456, @tid = 9;
SELECT TOP 1 ...
我知道你在想“只做@R12,2”,是的,这是可行的,但我不想告诉你为什么没有那么简单。然而,制作@r 20,10是一个可行的选择,并且确实解决了这个问题

我发誓我没有疯,我希望我能发布一段视频来证明这一切。我以前见过变量的奇怪行为,但不是这样的。有什么想法吗?这听起来像是一个模糊的错误吗

下面是真正的查询(缩写为损坏的表名,告诉您它很难看):


这些问题总是让我感兴趣,所以我试图重现你看到的问题。到目前为止,以下代码是我获得此错误的唯一成功结果:

use demo 
go
if object_id('dbo.numbers', 'U') is not null
    drop table dbo.numbers
create table numbers (
    nid int primary key
   ,d12_2 decimal(12, 2))
insert dbo.numbers
select * from (values 
(1, 1234567890.12),
(2, 12345)) i(n,d)
go
declare @d14_10 decimal(14, 10)
select @d14_10 = (select top 1 d12_2
                    from dbo.numbers
                    where nid = 1)
go
declare @d14_10 decimal(14, 10)
select @d14_10 = (select top 1 d12_2
                    from dbo.numbers
                    where nid = 2)
具有以下输出:

Msg 8115, Level 16, State 8, Line 15
Arithmetic overflow error converting numeric to data type numeric.
Msg 8115, Level 16, State 8, Line 20
Arithmetic overflow error converting numeric to data type numeric.
我能得到这个错误的唯一方法是尝试转换一些不适合新类型的东西(duh…),因为精度在增加(点后面的空格),不可能在那里遇到麻烦。这让我得出结论,在您的数据中一定有一条t3.r=>10000的记录

这一点一开始似乎很奇怪,因为t3.r有一个已知的值,它更小。然而。。。我想知道你是如何确定这个值的?24.79是否可能是成功运行的最后一个值


唯一的另一种选择是,该问题超出了演示示例的范围。

我非常确定24.79不是问题所在,但我想提及实际值。@tid的问题也不是具体的-1,当我将其设置为结果集中产生多条记录的任何值时,都会出现相同的错误(实际查询使用SELECT TOP 1)。对不起,我的问题很简短。我会相应地更新它。你能把所有的表定义添加到你的帖子中吗?真正的13个表总共有579列。我试图将我的简化版本限制为似乎相关的值。在实查询中,联接或WHERE子句(t3.r除外)中的每个值都是一个int(主要是IDENTITY cols)。我将在上面的问题中添加一些简单的table def。谢谢。这是完全可能的
声明@r1十进制(14,10),@r2十进制(12,2);设置@r2=10000;设置@r1=@r2
你无法控制它在何处施放,一个超出范围的值可能会导致这种情况,即使它不是
TOP
ONE。@anthony444我还有一个问题。如果您多次运行同一查询,结果会不同(我的意思是,有时您会收到一个算术错误,有时它会工作?)。。。如果您识别了一个示例,那么您可以使用查询生成一个游标,并手动强制转换值,以专门检查引发错误的行?另一个选项是,异常是由其他字段引起的,而不是由转换引起的(只是尝试从开箱即用的方式查看):DThanks@Tristan。我在上面的原始问题中添加了“real”查询(缩写为损坏的表名)。我知道它是24.79,因为我可以在不转换它的情况下获取值,或者如果@r被声明为十进制(12,2),或者如果我只是硬编码-1,那么在原始代码中是否还有其他对t3.r的引用?这将是高度相关的,但我有一些困难,试图阅读您发布的代码。(这件衣服做得很好。)啊,对不起。t3.r相当于“real”查询中的pc.pc_成本。我使用用于测试的CONVERT函数粘贴了查询。我更新了上面的“real”查询,使事情变得更清楚。还有一个问题,因为错误没有指定导致错误的列,是否有可能一个连接列的数据类型与另一个不同?好问题。昨天我仔细检查了连接中的每一列类型,它们都是int。