TSQL使用BIGINT进行算术溢出

leo*_*nfo 7 sql t-sql

有人可以为我澄清当我尝试在下面的示例中设置变量@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.
*/
Run Code Online (Sandbox Code Playgroud)

我现在能想到的是,在内部,SQL开始做数学评估乘法并将临时结果放入INT然后它将它转换为BIGINT.

但是,如果我在我的数字列表中添加1.0*,则没有错误,因此我相信在这段时间内SQL使用float作为临时结果,然后将其转换为BIGINT

DECLARE @b BIGINT
SET @b =   1.0  *  7*11*13*17*19*23*29*31
/*
NO ERROR
*/
Run Code Online (Sandbox Code Playgroud)

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

[我正在使用SQL 2008]

[编辑]

感谢Nathan的链接.这是我不知道的好信息,但我仍然不明白为什么我会得到错误,为什么我要做"技巧"来获得这样一个简单的脚本.

这是我应该知道如何作为程序员处理的事情吗?

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

Nat*_*itt 9

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

注意
当您使用+, - ,*,/或%算术运算符执行int,smallint,tinyint或bigint常量值到float,real,decimal或numeric数据类型的隐式或显式转换时,SQL的规则服务器在计算数据类型时适用,并且表达式结果的精度根据查询是否自动参数化而不同.

因此,查询中的类似表达式有时会产生不同的结果.当查询不是自动参数化时,常量值首先转换为数字,其精度只要大到足以保存常量的值,然后再转换为指定的数据类型.例如,常数值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.

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

DECLARE @a BIGINT
SET @a = 7*11*13*17*19*23*29*CONVERT(BIGINT, 31)
Run Code Online (Sandbox Code Playgroud)


Pau*_*gle 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
Run Code Online (Sandbox Code Playgroud)

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