使用BIGINT的TSQL算术溢出

使用BIGINT的TSQL算术溢出,sql,tsql,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,然后将其转换为BIG

有人能为我澄清一下,在下面的示例中,当我试图设置变量@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*,则不会出现错误,因此我认为这次SQL使用float作为临时结果,然后将其转换为BIGINT

DECLARE @b BIGINT
SET @b =   1.0  *  7*11*13*17*19*23*29*31
/*
NO ERROR
*/
坦白地说,我不认为代码有什么问题。。。这很简单

[我正在使用SQL 2008]

[编辑]

谢谢内森的邀请。 这是我不知道的好信息,但我仍然不明白为什么我会出错,为什么我要做一些“技巧”来让这样一个简单的脚本工作

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


或者,这是一个bug,如果是的话,我会考虑这个问题。

< P>当你这样计算时,单个的数字被存储得足够大,可以保持这个数,即:数字(1,0)。看看这个:

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

因此,类似的表达在 查询有时会产生 不同的结果。当查询不可用时 自动参数化,常量值 首先转换为数值,其 精度刚好可以容纳 常量的值,在 正在转换为指定的数据类型。 例如,常量值1为 转换为数字(1,0),并且 将常量值250转换为 数字(3,0)

当查询自动参数化时 常量值始终转换为 转换为之前的数字(10,0) 最终的数据类型。当/ 操作员参与,不仅可以 结果类型的精度在不同类型中有所不同 类似的查询,但结果值 也可以不同。例如 自动参数化的结果值 包含表达式的查询 选择铸造(1.0/7为浮动)将 与的结果值不同 同一个查询不是 自动参数化,因为结果 自动参数化查询的 截断以适合数字(10, 0)数据类型。更多信息 关于参数化查询,请参见 简单的参数化


编辑 这不是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)

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

同样,您可以这样做:

DECLARE @a BIGINT,
        @b BIGINT

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

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

我认为您是正确的。为什么SQL应该推断7是bigint而不是int?它甚至不认为它是int,它认为它是
数值(1,0)
。Nathan,你是对的。问题是我为什么会出错。为什么SQL不在需要时分配正确的数据类型?好的,但我仍然认为这种定义的行为是错误的。如果我不将变量定义为BIGINT,我就会理解这种行为。但是,一旦我将变量定义为BIGINT,SQL就应该完成其余的工作。这就是抛出错误的部分。任何编程环境都可以从右向左运行,只是有些环境可能会自动升级为另一种整数数据类型。失败的不是变量,而是计算。不要抱怨SQL Server是如何做到这一点的,它的设计方式就是它的设计方式。只是因为这不符合你的特定偏见,并不意味着它的设计方式是无效的。我相信他们有充分的理由这样做。您需要在database.HLGEM的限制范围内生活,如果没有人会“抱怨”事情的工作方式,那么就不需要改进。我想你至少同意这个信息不是很清楚。你可以在很多情况下看到这个消息……LeoFio你需要考虑的是:<代码>声明@ A为VARCHAR(10);设置@a=1+2+3如果将
@a
设置为“123”或“6”,那么
@a=1+(2+3)
会产生什么结果?SQL很少会为任何事情“做其余的事情”,它主要只是尝试在功能上保持一致。