Я знаю, что это довольно старый вопрос, но ни один из существующих ответов не кажется, обратиться «почему?» аспект к вашему вопросу.
Во-первых, каков тип данных для ваших литералов? Я не был уверен (и не смотрел его), так что я побежал следующее:
select 1.4 union all
select 'frob'
который возвращает ошибку:
Msg 8114, Level 16, State 5, Line 1
Error converting data type varchar to numeric.
Итак, 1.4
и другие литералы numeric
- aka decimal
.
Далее, что тип возвращаемого значения функции SUM
, если принят decimal(p,s)
:
decimal(38, s)
Итак, типы данных 3 SUM
выражений в запросе являются decimal(38,1)
, decimal(38,4)
и decimal(38,2)
.Учитывая эти 3 типа данных, доступных для выбора, decimal(38,1)
является окончательным выбранным типом, основанным на правилах для differing precisions and scales.
The result precision and scale have an absolute maximum of 38. When a result precision is greater than 38, the corresponding scale is reduced to prevent the integral part of a result from being truncated.
Итак, наконец, вернуться к документации на decimal
:
By default, SQL Server uses rounding when converting a number to a decimal or numeric value with a lower precision and scale. However, if the SET ARITHABORT option is ON, SQL Server raises an error when overflow occurs. Loss of only precision and scale is not sufficient to raise an error.
Так что это ваш конечный результат.
На первом таком типе может показаться удивительным, пока вы не поймете, что в целом, sum
будет работать против нескольких строк, и это легко можно для нескольких значений заданной точности и масштаба, увлекают их собственный тип данных. decimal(38,s)
дает максимально возможное пространство для размещения любых переполнений без потери точности при возникновении ошибки SUM()
и означает, что окончательный тип данных может быть определен до выполнения запроса.