Sql-Server

為什麼“SELECT POWER(10.0, 38.0);”拋出算術溢出錯誤?

  • August 28, 2020

我正在更新我的IDENTITY溢出檢查腳本以說明DECIMALNUMERIC IDENTITY

作為檢查的一部分,我計算每一IDENTITY列的數據類型範圍的大小;我用它來計算該範圍的百分比已用盡。對於該範圍的大小,DECIMAL精度在哪裡。NUMERIC 2 * 10^p - 2p

我創建了一堆帶有DECIMALNUMERIC IDENTITY列的測試表,並嘗試按如下方式計算它們的範圍:

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. 

我將它縮小到IDENTITY類型的列DECIMAL(38, 0)(即具有最大精度),所以我然後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()類型為 的輸出轉換FLOATNUMERIC(尤其是在FLOAT具有更高優先級時)?
  • 如何為所有可能的精度(當然包括)動態計算 aDECIMAL或列的範圍?NUMERIC``p = 38

POWER文件中:

句法

POWER ( float_expression , y )

論據

float_expression

float類型或可以隱式轉換為float的類型的表達式

y

是提高float_expression的冪。*y可以是精確數值或近似數值數據類型類別的表達式,*數據類型除外。

返回類型

返回與float_expression中送出的類型相同的類型。例如,如果將小數(2,0) 作為 float_expression 送出,則返回的結果為小數(2,0)。


float如有必要,第一個輸入將被隱式轉換為。

float內部計算由標準 C 執行時庫 (CRT) 函式使用算術執行pow

然後將float輸出pow轉換回左側操作數的類型(暗示numeric(3,1)當您使用文字值 10.0 時)。

在您的情況下使用顯式float工作正常:

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

10 38的精確結果不能儲存在 SQL Server 中decimal/numeric,因為它需要 39 位精度(1 後跟 38 個零)。最大精度為 38。

引用自:https://dba.stackexchange.com/questions/6900