TSQL使用BIGINT进行算术溢出

时间:2011-02-16 16:04:30

标签: sql tsql

当我尝试在下面的示例中设置变量@a时,有人可以为我澄清为什么会出现错误?

DECLARE @a BIGINT
SET @a = 7*11*13*17*19*23*29*31
/*
ERROR:
Msg 8115, Level 16, State 2, Line 1
Arithmetic overflow error converting expression to data type int.
*/

我现在能想到的是,在内部,SQL开始进行数学运算,评估乘法并将临时结果放入INT,然后将其转换为BIGINT。

但是,如果我在我的数字列表中添加 1.0 * ,则没有错误,因此我认为这次使用float作为临时结果,然后将其转换为BIGINT < / p>

DECLARE @b BIGINT
SET @b =   1.0  *  7*11*13*17*19*23*29*31
/*
NO ERROR
*/

坦率地说,我没有看到代码有什么问题......它很简单......

[我正在使用SQL 2008]

[编辑]

感谢Nathan link。  这是我不了解的好信息,但我仍然不明白为什么我会收到错误,为什么我要做“技巧”来获得这样一个简单的脚本。

作为程序员,我应该知道如何处理它?<​​/ p>

或者,这是一个错误,如果是这样,我会考虑关闭这个问题。

2 个答案:

答案 0 :(得分:9)

当你进行这样的计算时,个别数字的存储量足以容纳该数字,即:数字(1,0)。看看这个:

  

注意
  当你使用+, - ,*时,   /,或%算术运算符   执行隐式或显式   转换int,smallint,tinyint,   或者bigint常量值   浮点数,实数,十进制或数字数据   类型,SQL Server的规则   在计算数据时适用   表达式的类型和精度   结果取决于是否   查询是否自动参数化。

     

因此,类似的表达方式   查询有时会产生   不同的结果。当查询不是   自动参数化,恒定值   首先转换为数字,其中   精度足以容纳   之前的常数的值   转换为指定的数据类型。   例如,常数值1是   转换为数字(1,0),和   常数值250被转换为   数字(3,0)。

     

当查询是自动参数化时,   常量值始终转换为   转换为之前的数字(10,0)   最终的数据类型。当。。。的时候 /   涉及运营商,不仅可以   结果类型的精度不同   类似的查询,但结果值   也可以有所不同。例如,   自动参数化的结果值   包含表达式的查询   SELECT CAST(1.0 / 7 AS float)会   与结果值不同   相同的查询不是   自动参数化,因为结果   自动参数化查询将是   截断以适应数字(10,   0)数据类型。欲获得更多信息   关于参数化查询,请参阅   简单的参数化。

http://msdn.microsoft.com/en-us/library/ms187745.aspx


修改

这不是SQL Server中的错误。它从同一页面说明:

  

int数据类型是SQL Server中的主要整数数据类型。

  

SQL Server不会自动将其他整数数据类型(tinyint,smallint和int)提升为bigint。

这是定义的行为。作为程序员,如果您有理由相信您的数据会溢出数据类型,则需要采取预防措施来避免这种情况。在这种情况下,只需将其中一个数字转换为BIGINT即可解决问题。

DECLARE @a BIGINT
SET @a = 7*11*13*17*19*23*29*CONVERT(BIGINT, 31)

答案 1 :(得分:5)

在第一个示例中,SQL Server将INT列表相乘,并发现结果太大而不能成为INT并生成错误。在第二个例子中,它注意到有一个浮点数,因此它首先将所有INT转换为浮点数,然后进行乘法运算。

同样,你可以这样做:

DECLARE @a BIGINT,
        @b BIGINT

set @b = 1
SET @a = @b*7*11*13*17*19*23*29*31

这很好用,因为它注意到有一个BIGINT,所以它将所有INT转换为BIGINT,然后进行乘法。