web-dev-qa-db-ja.com

「SELECT POWER(10.0、38.0);」を実行する理由算術オーバーフローエラーをスローしますか?

私のIDENTITYオーバーフローチェックスクリプト を更新して、 DECIMALNUMERICIDENTITY を考慮しています。

チェックの一部として、すべてのIDENTITY列のデータ型の範囲のサイズを計算します。これを使用して、その範囲の何パーセントが使い果たされているかを計算します。 DECIMALおよびNUMERICの場合、その範囲のサイズは_2 * 10^p - 2_ です。ここで、pは精度です。

DECIMAL列とNUMERICIDENTITY列を含む一連のテストテーブルを作成し、次のようにそれらの範囲を計算しようとしました。

_SELECT POWER(10.0, precision)
FROM sys.columns
WHERE 
       is_identity = 1
   AND type_is_decimal_or_numeric
;
_

これにより、次のエラーがスローされました。

_Msg 8115, Level 16, State 6, Line 1
Arithmetic overflow error converting float to data type numeric. 
_

タイプDECIMAL(38, 0)IDENTITY列(つまり、最大精度)に絞り込んだので、その値に対して直接POWER()計算を試みました。

次のすべてのクエリ

_SELECT POWER(10.0, 38.0);
SELECT CONVERT(FLOAT, (POWER(10.0, 38.0)));
SELECT CAST(POWER(10.0, 38.0) AS FLOAT);
_

また、同じエラーが発生しました。

  • SQL Serverが POWER() の出力をFLOATタイプのNUMERICに変換しようとする理由(特に FLOATがより高い優先順位 )?
  • すべての可能な精度(もちろん、_p = 38_を含む)のDECIMALまたはNUMERIC列の範囲を動的に計算するにはどうすればよいですか?
15
Nick Chammas

POWER documentation から:

構文

POWER ( float_expression , y )

議論

float_expression
タイプfloatであるか、暗黙的にfloatに変換できるタイプです。

y
は、float_expressionを累乗する力です。 yは、ビットデータ型を除いて、正確な数値または近似数値データ型のカテゴリの式にすることができます。

戻り型

float_expressionで送信されたものと同じ型を返します。たとえば、decimal(2,0)がfloat_expressionとして送信された場合、返される結果はdecimal(2,0)です。


最初の入力は、必要に応じて暗黙的にfloatにキャストされます。

内部計算は、標準Cランタイムライブラリ(CRT)関数floatによるpow演算を使用して実行されます。

次に、floatからのpow出力は、左側のオペランドのタイプにキャストバックされます(リテラル値10.0を使用すると、numeric(3,1)と暗黙的に示されます)。

明示的にfloatを使用すると、あなたの場合はうまくいきます:

SELECT POWER(1e1, 38);
SELECT POWER(CAST(10 as float), 38.0);

10の正確な結果38 SQL Serverに保存できないdecimal/numericこれは、39桁の精度が必要になるためです(1の後にゼロが38個続く)。最大精度は38です。

18
Martin Smith