【问题标题】:Sql Server SUM function with Int and Decimal Convertion具有 Int 和 Decimal 转换的 Sql Server SUM 函数
【发布时间】:2017-12-22 16:22:40
【问题描述】:

最近我在玩 SQL Server 数据类型,并将大量数据放入表中,并试图找出 Varchar 和 Numeric 数据的性能。但是,我遇到了一些错误,我认为不应该是这样,但确实如此。我的问题如下:

我有一张桌子:

create table sa(f1 varchar(100))

我有一个向表中插入 100000 个数据的存储过程:

create proc sad
as
begin
    declare @i int=0
    while @i<100000
    begin
       insert into sa values(@i)
       set @i=@i+1
    end
end


exec sad

我已经测试了以下内容:

select CONVERT(int,f1) from sa  //Works Fine, i tested after the Problem
select sum(convert(int,f1)) from sa  //Didn't Worked, So i tested above and Below
select sum(convert(decimal(18,2),f1)) from sa //And, it again works fine

但是,当我总结将 F1 转换为 Int 时,它显示了一个错误。
但是,当我只选择 Converting to Int 时,它很好。
而且,当我总结将 F1 转换为十进制时,它工作正常。

SUM函数的数据类型是什么?
在上述数据上,它适用于 Decimal 但不适用于 Int?
为什么?

我收到以下错误

将表达式转换为数据类型 int 时出现算术溢出错误。

【问题讨论】:

  • 请复制并粘贴您遇到的错误...
  • 对不起,...我用我得到的错误编辑了我的问题
  • 我试图找出性能问题,同时使用 Varchar 和 Numeric 数据类型
  • 你的总价值会超过20亿吗?
  • 如果您对int 求和,SUM 将为int,但如果您对decimal 求和,SUM 将为decimal。有关更多详细信息,请参阅下面的答案...

标签: sql sql-server sql-server-2008


【解决方案1】:

您的总和为 INT,其范围无法容纳该总和。

DECIMAL 可以。

从 1 到 99999 的所有值的总和为 4999950000,最大 INT 值为 2147483647,不到总和的一半。

当你对 INT 求和时,你会得到一个新的 INT。当您对 DECIMAL 求和时,您将得到一个新的 DECIMAL,因此输入类型定义了输出类型。

您可以改用bigint,它应该“没问题”。

另外,请注意,请不要将数字存储为文本

【讨论】:

  • 是的,我不应该。但为什么? SUM 函数在我转换时是否将其数据类型派生为 INT?
  • 是的。输入为 INT,输出为 INT。
  • 如何,Sum 取决于 INT,这里 Convert into INT 效果很好。而且,转换成十进制也很好用。那么,为什么 Summing(int) 不起作用,但它可以转换,但为什么 sum 起作用 Decimal?
  • SUM 运算在某种程度上依赖于内部数据类型
  • 总和溢出,如错误消息所述。尝试将 1 到 10 的所有值相加,并保持在 5 以下。这是同样的问题。 INT 数据类型不能容纳总和,它对它来说太大了。
【解决方案2】:

根据 MS 文档(请参阅 https://docs.microsoft.com/en-us/sql/t-sql/functions/sum-transact-sql),SUM() 函数根据您要添加的列的数据类型返回不同类型的值:如果列的类型为 inttinyint ,或smallint,则SUM 返回int 类型的值。

转换为bigintdecimal 使SUM() 返回更大的数据类型,这解释了为什么在这种情况下您没有溢出。

【讨论】:

  • 好的,那么 Sum 取决于我们要求和的 Column 数据类型。谢谢你。这让我很清楚。
【解决方案3】:

预计您已超过 SQL Server 允许的最大 int 值 (2,147,483,647) - 请参阅 https://docs.microsoft.com/en-us/sql/t-sql/data-types/int-bigint-smallint-and-tinyint-transact-sql

十进制允许更高的限制,最高可达 10^38 - 1(即 1 后面有 38 个零) - 请参阅 https://docs.microsoft.com/en-us/sql/t-sql/data-types/decimal-and-numeric-transact-sql

但是,如果值的类型为int,我不建议转换为decimalDecimal 值在小数点后的数字具有已知精度和比例(例如货币、百分比等)时很有用。正如另一位海报所建议的那样,这里最好的转换是 bigint

select sum(cast(f1 as bigint)) from sa

【讨论】:

    【解决方案4】:

    看起来你的结果总和对于int来说太大了,使用bigint,同时检查int, bigint, smallint, and tinyint (Transact-SQL)

    select sum(convert(bigint,f1)) from sa
    

    【讨论】:

      猜你喜欢
      • 2020-10-14
      • 1970-01-01
      • 1970-01-01
      • 2020-08-05
      • 2021-08-31
      • 2014-09-16
      • 2012-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多