可以在执行 POWER(x,y) 之前检测到何时会发生算术溢出吗?
Possible to detect when arithmetic overflow would occur before POWER(x,y) is executed?
示例:
-- inputs
declare @x decimal(28,10) = 10001.0
declare @y decimal(18,6) = 7.0
-- later on, inside a udf
select POWER(@x, @y)
结果:
Msg 8115, Level 16, State 6, Line 13
Arithmetic overflow error converting float to data type numeric.
我明白为什么会发生溢出。我的问题是,是否有可能检测到,
POWER 执行之前,会不会溢出?请注意,代码在 UDF 中 运行,因此不能使用 TRY...CATCH。如果我能提前检测到它,我可以采取避免措施(例如结果为return NULL,这很适合我的要求)。
您可以使用 Try-Catch 或者您可以使用公式来预测输出数字和 return NULL。从 here
预测位数的公式
预测幂函数的位数
Declare @Num DECIMAL(28,10) = 10001
,@Exponent DECIMAL(28,10) = 7
,@NumOfDigits INT
/*Predict number of digits from power function*/
SELECT @NumOfDigits = FLOOR(1 + @exponent* CAST(LOG(@Num,10) AS DECIMAL(38,10)))
SELECT
CASE WHEN @NumOfDigits <= 38 /*Max decimal precision, return type from POWER function according to https://docs.microsoft.com/en-us/sql/t-sql/functions/power-transact-sql?view=sql-server-ver15*/
- 10 /*Scale of @Num. Need to leave enough digits to record decimal places*/
THEN POWER(@Num,@Exponent) /*If less than or equal to precision, return value*/
ELSE NULL /*If outside precision, just returns NULL. Could update to return something else*/
END
示例:
-- inputs
declare @x decimal(28,10) = 10001.0
declare @y decimal(18,6) = 7.0
-- later on, inside a udf
select POWER(@x, @y)
结果:
Msg 8115, Level 16, State 6, Line 13
Arithmetic overflow error converting float to data type numeric.
我明白为什么会发生溢出。我的问题是,是否有可能检测到, POWER 执行之前,会不会溢出?请注意,代码在 UDF 中 运行,因此不能使用 TRY...CATCH。如果我能提前检测到它,我可以采取避免措施(例如结果为return NULL,这很适合我的要求)。
您可以使用 Try-Catch 或者您可以使用公式来预测输出数字和 return NULL。从 here
预测位数的公式预测幂函数的位数
Declare @Num DECIMAL(28,10) = 10001
,@Exponent DECIMAL(28,10) = 7
,@NumOfDigits INT
/*Predict number of digits from power function*/
SELECT @NumOfDigits = FLOOR(1 + @exponent* CAST(LOG(@Num,10) AS DECIMAL(38,10)))
SELECT
CASE WHEN @NumOfDigits <= 38 /*Max decimal precision, return type from POWER function according to https://docs.microsoft.com/en-us/sql/t-sql/functions/power-transact-sql?view=sql-server-ver15*/
- 10 /*Scale of @Num. Need to leave enough digits to record decimal places*/
THEN POWER(@Num,@Exponent) /*If less than or equal to precision, return value*/
ELSE NULL /*If outside precision, just returns NULL. Could update to return something else*/
END