【问题标题】:Arithmetic Overflow in SQL ServerSQL Server 中的算术溢出
【发布时间】:2011-06-11 14:32:44
【问题描述】:

我有一个存储过程,它将两个坐标对之间的距离计算为浮点数。我正在尝试使用它来过滤值列表,但出现算术溢出错误。查询是:

SELECT * FROM Housing h  WHERE convert(float, dbo.CalculateDistance(35, -94, h.Latitude, h.Longitude)) <= 30.0

哪些错误:

消息 8115,级别 16,状态 6,第 1 行算术溢出错误 将浮点数转换为数字数据类型。

存储过程供参考:

CREATE FUNCTION [dbo].[CalculateDistance]
    (@Longitude1 DECIMAL(8,5),
    @Latitude1   DECIMAL(8,5),
    @Longitude2  DECIMAL(8,5),
    @Latitude2   DECIMAL(8,5))
RETURNS FLOAT
AS
BEGIN
DECLARE @Temp FLOAT

SET @Temp = SIN(@Latitude1/57.2957795130823) * SIN(@Latitude2/57.2957795130823) + COS(@Latitude1/57.2957795130823) * COS(@Latitude2/57.2957795130823) * COS(@Longitude2/57.2957795130823 - @Longitude1/57.2957795130823)

IF @Temp > 1
    SET @Temp = 1
ELSE IF @Temp < -1
    SET @Temp = -1

RETURN (3958.75586574 * ACOS(@Temp) )

END

我们也尝试将结果转换为十进制,但没有任何效果。

【问题讨论】:

  • 存储过程单独运行是否有效?
  • 它说它正在将浮点数转换为数字。除了可能在格式化结果时选择本身之外,我看不到任何地方应该发生这种情况?

标签: sql sql-server math


【解决方案1】:

您的输入是 DECIMAL(8,5)。这意味着方程由例如SIN(DECIMAL(8,5) / 57.2957795130823) 组成。其中 57.2957795130823 不能表示为 DECIMAL(8,5)。

这意味着由于数据类型不同,您有一个隐含的 CAST 操作。在这种情况下,似乎 57.2957795130823 被强制转换为 DECIMAL(8,5) [a numeric],并导致溢出。

我会推荐以下任何一种:
- 更改您的函数以将输入作为浮点数。即使使用数字调用函数
- 将 57.2957795130823 更改为 57.29577
- 将 DECIMAL 显式转换为 FLOAT

【讨论】:

  • 我想过这个:57.2957795130823 是十进制(15,13)。小数除法遵循一些神秘的规则:stackoverflow.com/questions/423925/…。也试试 SELECT SIN(CAST(-94 As decimal(8,5)) / 57.2957795130823 )
【解决方案2】:

我会尝试转换我的一些算术以防万一

convert(float,(SIN(@Latitude1/57.2957795130823)) * convert(float,(SIN(@Latitude2/57.2957795130823)) + convert(float,(COS(@Latitude1/57.2957795130823)) * convert(float,(COS(@Latitude2/57.2957795130823)) * convert(float,COS(@Longitude2/57.2957795130823 - @Longitude1/57.2957795130823))

你可以使用的另一件事是

IFNULL(convert(float,(SIN(@Latitude1/57.2957795130823)),0.00)

您的结果可能返回空值

【讨论】:

  • SIN 输出已经是浮点数:输入也转换为浮点数
【解决方案3】:

这是你与 = 30.0

的比较

30.0 是小数(3,2)(带小数点的常量在 SQL Server 中是小数)并且浮点输出不会强制转换。见:

SELECT 30.0 AS What INTO dbo.DataType
Go
SELECT t.name, c.*
FROM sys.columns c JOIN sys.types t ON c.system_type_id = t.system_type_id
WHERE object_id = OBJECT_ID('dbo.DataType')
GO
DROP TABLE dbo.DataType
GO

试试

... <= CAST(30.0 As float)

【讨论】:

    【解决方案4】:

    您正在返回一个浮点数。您不应该对纬度和经度变量也使用浮点数吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-14
      相关资源
      最近更新 更多