Арифметическое переполнение в SQL Server - PullRequest
5 голосов
/ 11 июня 2011

У меня есть хранимая процедура, которая вычисляет расстояние между двумя парами координат в виде числа с плавающей запятой. Я пытаюсь использовать это для фильтрации списка значений, но получаю арифметическую ошибку переполнения. Запрос:

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

также пытались преобразовать результат в десятичную без эффекта.

Ответы [ 4 ]

4 голосов
/ 11 июня 2011

Ваши входы являются десятичными (8,5). Это означает, что уравнения состоят, например, из SIN(DECIMAL(8,5) / 57.2957795130823). Где 57.2957795130823 не может быть представлен как ДЕСЯТИЧНЫЙ (8,5).

Это означает, что у вас есть скрытая операция CAST из-за другого типа данных. В этом случае может показаться, что 57.2957795130823 приводится к DECIMAL (8,5) [число] и вызывает переполнение.

Я бы порекомендовал любой из них:
- Изменение вашей функции, чтобы принимать входы как плавающие. Даже если функция вызывается с цифрами
- Изменение 57,2957795130823 на 57,29577
- Явное приведение ДЕСЯТИЛЕТОВ к ПЛАВАМ

1 голос
/ 11 июня 2011

Это ваше сравнение с <<code>= 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)
1 голос
/ 11 июня 2011

Я бы попробовал преобразовать часть своей арифметики на всякий случай

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)

Ваши результаты могут возвращать нули

0 голосов
/ 11 июня 2011

Вы возвращаете поплавок. Разве вы не должны использовать float для переменных широты и долготы?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...