Вместо того, чтобы больше вмешиваться в ответ Мартина, я добавлю остальные мои выводы, касающиеся POWER()здесь.
Держись за свои трусики.
преамбула
Сначала я представляю вам экспонат А, документацию MSDN дляPOWER() :
Синтаксис
POWER ( float_expression , y )
аргументы
float_expression
Выражение типа float или типа, который можно неявно преобразовать в float.
Типы возврата
Такой же как float_expression.
Из этой последней строки вы можете сделать вывод, что POWER()тип возвращаемого значения - FLOATно прочитайте еще раз. float_expressionимеет тип типа float или типа, который может быть неявно преобразован в тип float. Таким образом, несмотря на название, на float_expressionсамом деле это может быть a FLOAT, a DECIMALили an INT. Так как выходные данные POWER()такие же, как и у float_expression, они также могут быть одним из этих типов.
Итак, у нас есть скалярная функция с типами возвращаемых данных, которые зависят от входных данных. Может ли это быть?
наблюдения
Я представляю вам экспонат B, тест, демонстрирующий, что POWER()вывод его данных выполняется в зависимости от типа входных данных .
SELECT
POWER(10, 3) AS int
, POWER(1000000000000, 3) AS numeric0 -- one trillion
, POWER(10.0, 3) AS numeric1
, POWER(10.12305, 3) AS numeric5
, POWER(1e1, 3) AS float
INTO power_test;
EXECUTE sp_help power_test;
DROP TABLE power_test;
Соответствующие результаты:
Column_name Type Length Prec Scale
-------------------------------------------------
int int 4 10 0
numeric0 numeric 17 38 0
numeric1 numeric 17 38 1
numeric5 numeric 17 38 5
float float 8 53 NULL
То , что кажется, происходит то , что POWER()забросы float_expressionв наименьшему типу , который соответствует его, не включая BIGINT.
Таким образом, происходит SELECT POWER(10.0, 38);сбой с ошибкой переполнения, поскольку 10.0происходит приведение к типу, NUMERIC(38, 1)который недостаточно велик, чтобы содержать результат 10 38 . Это связано с тем, что 10 38 расширяется до 39 цифр перед десятичной запятой, тогда как NUMERIC(38, 1)может хранить 37 цифр до десятичной запятой и одну после нее. Следовательно, максимальное значение NUMERIC(38, 1)может быть 10 37 - 0,1.
Вооружившись этим пониманием, я могу придумать еще одну ошибку переполнения следующим образом.
SELECT POWER(1000000000, 3); -- one billion
Один миллиард (в отличие от одного триллиона из первого примера, который приведен NUMERIC(38, 0)) - достаточно мал, чтобы уместиться в INT. Однако миллиард, возведенный в третью степень, слишком велик INT, поэтому возникает ошибка переполнения.
Несколько других функций демонстрируют аналогичное поведение, где их тип вывода зависит от их ввода:
- Математические функции :
POWER(), CEILING(), FLOOR(), RADIANS(), DEGREES(), иABS()
- Системные функции и выражение :
NULLIF(), ISNULL(), COALESCE(), IIF(), CHOOSE(), и CASEвыражение
- Арифметические операторы :
SELECT 2 * @MAX_INT;и то и другое SELECT @MAX_SMALLINT + @MAX_SMALLINT;, например, приводят к арифметическим переполнениям, когда переменные имеют именованный тип данных.
Вывод
В данном конкретном случае решение заключается в использовании SELECT POWER(1e1, precision).... Это сработает для всех возможных значений точности с момента 1e1приведения к нему FLOAT, который может содержать смехотворно большие числа .
Поскольку эти функции настолько распространены, важно понимать, что ваши результаты могут быть округлены или могут вызвать ошибки переполнения из-за их поведения. Если вы ожидаете или полагаетесь на конкретный тип данных для своего вывода, явно приведите соответствующий ввод при необходимости.
Итак, дети, теперь, когда вы это знаете, вы можете идти дальше и процветать.