我不会再干预Martin的回答,而是在此添加我的其余发现POWER()
。
坚持你的内裤。
前言
首先,我向您展示A 的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
10亿(相对于第一个示例中的1万亿,后者被强制转换为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
,因此可以适用于所有可能的精度,该精度可以容纳大量的数字。
由于这些函数非常普遍,因此必须了解结果可能会被舍入或由于其行为而导致溢出错误,这一点很重要。如果您期望或依赖于特定的数据类型来输出,请根据需要显式转换相关输入。
因此,孩子们,既然您知道这一点,就可以继续前进并繁荣起来。