算术溢出错误

Joh*_*one 5 sql-server t-sql sql-server-2008-r2 errors

如果我运行此代码:

select 99999 * 9999
Run Code Online (Sandbox Code Playgroud)

结果 = 999890001

如果我运行此代码:

select 9999923 * 99999999
Run Code Online (Sandbox Code Playgroud)

结果:

消息 8115,级别 16,状态 2,第 1 行
将表达式转换为数据类型 int 的算术溢出错误。

如果我运行以下代码:

select 922337299987987689745893 * 999999994564
Run Code Online (Sandbox Code Playgroud)

结果 = 922337294974162127011191918541325652

为什么我会在特定范围内收到此算术溢出错误?

Pau*_*ite 10

SQL Server 用于派生文字类型的规则很复杂,为了向后兼容,现在维护了一些奇怪的行为。例如,派生类型可能取决于是否应用了简单参数化。还有其他(未记录的)注意事项。

抛开这些注意事项,您面临的情况是比较简单的情况之一。无类型文字按integer它们适合该数据类型的时间进行类型化。结果的数据类型在* (Multiply) (Transact-SQL) 中指定

返回具有较高优先级的参数的数据类型。
有关详细信息,请参阅数据类型优先级 (Transact-SQL)

这两种数据类型都是integer(显然具有相同的优先级),因此结果的类型也为integer。当结果不合适时,可能会抛出错误(取决于设置)。

当使用CASTCONVERT作为(例如)bigint(其优先级高于integer)显式键入文字之一时,结果类型将为bigint,并且不会发生错误。

问题中的两个较大的常量分别输入为numeric(24,0)numeric(12,0)。将它们相乘的结果numeric(37,0)按照精度、比例和长度 (Transact-SQL) 中e1 * e2所示的规则输入:

结果精度:p1 + p2 + 1 = 24 + 12 + 1 = 37
结果比例:s1 + s2 = 0 + 0 = 0

结果类型:数字 (37,0)


iri*_*ias 6

在 Microsoft文档中,据说

任何非十进制表达式的精度和小数位数是为表达式的数据类型定义的精度和小数位数。

由于您的输入被视为 int,因此结果应该是 int,这意味着低于 2 147 483 647。如果它更大,它确实会引发错误。

如果您将一个输入转换为另一种数据类型,例如 bigint,它不会失败:

select 9999923 * cast(99999999 as bigint)
-- 999992290000077
Run Code Online (Sandbox Code Playgroud)