SQL CAST вызывает арифметику c Ошибка переполнения, даже если строка НЕ ​​находится в наборе результатов - PullRequest
0 голосов
/ 17 января 2020

Этот вопрос вызывает у нас недоумение ...

У нас есть запрос, который использует CAST для преобразования числа с плавающей запятой в десятичный, этот запрос объединяет несколько таблиц, чтобы найти строки для возврата. Одна из строк в одной из таблиц содержит значение, которое при переводе CAST в десятичное число вызывает ошибку переполнения Arithmeti c.

Странно то, что строка с этим значением НЕ является одной из строк, возвращаемых в наборе результатов.

Слишком упрощенный пример:

ID  Value
1   1.1
2   11.1
3   11111.1

Запрос:

SELECT Id, CAST(value as decimal(4,1))
FROM <complex number of joins>
WHERE <conditions that don't return row with Id 3>

... Арифметика c Ошибка

Если мы явно исключим эту строку в предложении WHERE ошибка исчезнет. Например. ГДЕ ... И ИД <> 3

.. Работает нормально

Кто-нибудь знает, как это возможно?

ПРИМЕЧАНИЕ. Проблема здесь не в том, что CAST не работает в строке с идентификатором 3! Проблема заключается в том, что предложение WHERE исключает строку с идентификатором 3, но запрос все равно не выполняется. Как запрос может завершиться неудачей, если строка со значением 11111.1 не возвращается предложением WHERE?

Ответы [ 3 ]

0 голосов
/ 17 января 2020

Кажется, что фильтр применяется после операции, а не наоборот. Ознакомьтесь с планом выполнения вашего запроса, чтобы понять порядок операций.

0 голосов
/ 17 января 2020

это не из-за того, что вы фильтруете данные, из-за того, где вы находитесь, а потому, что вы выбрали меньшую длину данных при приведении. Вы должны изменить его на DECIMAL (8,2), или там указана максимальная длина данных вашего столбца. Вы можете попробовать следующий пример, который объяснит вам, как это работает.

Следующее будет работать, поскольку оно не извлекает никаких данных

WITH yourTable AS (
    SELECT 1 AS ID, '1.1' AS Value UNION ALL
    SELECT 2, '11.1' UNION ALL
    SELECT 3, '11111.1313'
)

SELECT Id, CAST(value as decimal(4,1)) AS Id_casted
FROM yourTable WHERE yourTable.ID=4

Следующее не будет работать, так как десятичное значение превышает преобразование длина

WITH yourTable AS (
    SELECT 1 AS ID, '1.1' AS Value UNION ALL
    SELECT 2, '11.1' UNION ALL
    SELECT 3, '11111.1313'
)

SELECT Id, CAST(value as decimal(4,1)) AS Id_casted
FROM yourTable WHERE yourTable.ID=3

Вы можете решить эту проблему, изменив десятичную (4,1) = 3 ди git на десятичную (8,2) = 6 ди git

WITH yourTable AS (
    SELECT 1 AS ID, '1.1' AS Value UNION ALL
    SELECT 2, '11.1' UNION ALL
    SELECT 3, '11111.1313'
)

SELECT Id, CAST(value as DECIMAL(8,2)) AS Id_casted
FROM yourTable WHERE yourTable.ID=3

Простой следующий код показывает, что он генерирует исключение, так как максимальное значение будет 999,99 для чисел c (5,2), а когда вы назначите 1000, оно выдаст исключение

DECLARE @aritherror NUMERIC(5,2)
SET @aritherror = 1000.554
SELECT @aritherror
0 голосов
/ 17 января 2020

Тип DECIMAL(4, 1) означает всего четыре знака точности, одно из которых находится справа от десятичного знака. Таким образом, для размещения значения 11111.1 вам потребуется не менее DECIMAL(6, 1). Следующий запрос должен работать:

SELECT Id, CAST(value AS DECIMAL(6,1))
FROM <complex number of joins>
WHERE <conditions that don't return row with Id 3>

По крайней мере, вышеприведенное будет работать для трех предоставленных вами точек выборки данных.

Демо

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