Tri*_*nko 14 sql-server azure-sql-database
select POWER(2.,64.)
返回18446744073709552000
而不是18446744073709551616
. 它似乎只有 16 位精度(四舍五入第 17 位)。
即使使精度明确,select power(cast(2 as numeric(38,0)),cast(64 as numeric(38,0)))
它仍然返回四舍五入的结果。
这似乎是一个非常基本的操作,因为它可以像这样以 16 位精度任意剥离。它可以正确计算的最高值仅为POWER(2.,56.)
,失败为POWER(2.,57.)
。这里发生了什么?
真正可怕的是select 2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.;
实际上返回了正确的值。简洁到此为止。
Jac*_*las 17
从在线文档:
Run Code Online (Sandbox Code Playgroud)POWER ( float_expression , y )
参数
float_expression 是 float 类型或可以隐式转换为 float类型的表达式
这意味着无论您作为第一个参数传递的任何内容都将float(53)
在执行函数之前隐式转换为 a 。然而,情况并非(总是?)。
如果是这样,它将解释精度的损失:
将使用科学记数法的浮点值转换为十进制或数字仅限于精度为 17 位的值。任何精度高于 17 的值都舍入为零。
另一方面,文字2.
是类型numeric
……:
Run Code Online (Sandbox Code Playgroud)DECLARE @foo sql_variant; SELECT @foo = 2.; SELECT SQL_VARIANT_PROPERTY(@foo, 'BaseType'); GO
| (无列名) | | :--------------- | | 数字 |
dbfiddle在这里
…乘法运算符返回具有更高优先级的参数的数据类型。
似乎在 2016 (SP1) 上,保留了所有精度:
Run Code Online (Sandbox Code Playgroud)SELECT @@version; GO
| (无列名) | | :------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------- | | Microsoft SQL Server 2016 (SP1) (KB3182545) - 13.0.4001.0 (X64) <br> 2016 年 10 月 28 日 18:17:30 <br> 版权所有 (c) Microsoft Corporation<br> Windows Server 上的 Express Edition(64 位) 2012 R2 标准 6.3 <X64>(内部版本 9600:)(管理程序)<br> |
Run Code Online (Sandbox Code Playgroud)SELECT POWER(2.,64.); GO
| (无列名) | | :-------------------- | | 18446744073709551616 |
dbfiddle在这里
…但在 2014 (SP2) 上,它们不是:
Run Code Online (Sandbox Code Playgroud)SELECT @@version; GO
| (无列名) | | :------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------------------------------------- | | Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64) <br> 2016 年 6 月 17 日 19:14:09 <br> 版权所有 (c) Microsoft Corporation<br> Windows NT 上的 Express Edition(64 位) 6.3 <X64>(内部版本 9600:)(管理程序)<br> |
Run Code Online (Sandbox Code Playgroud)SELECT POWER(2.,64.); GO
| (无列名) | | :-------------------- | | 18446744073709552000 |
dbfiddle在这里
Pau*_*ite 14
2 64的结果完全可以表示float
(并且real
就此而言)。
当这个精确的结果被转换回numeric
(第一个POWER
操作数的类型)时,问题就出现了。
在引入数据库兼容性级别 130 之前,SQL Serverfloat
将numeric
隐式转换四舍五入到最多 17 位数字。
在兼容级别 130 下,转换过程中尽可能保留精度。知识库文章中记录了这一点:
SQL Server 2016 在处理某些数据类型和不常见操作方面的改进
要在 Azure SQL 数据库中利用此功能,您需要将 设置COMPATIBILITY_LEVEL
为 130:
ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL = 130;
Run Code Online (Sandbox Code Playgroud)
需要进行工作负载测试,因为新的安排不是万能的。例如:
SELECT POWER(10., 38);
Run Code Online (Sandbox Code Playgroud)
...应该抛出错误,因为 10 38不能存储numeric
(最大精度为 38)。120兼容下会出现溢出错误,但130下的结果是:
99999999999999997748809823456034029568 -- (38 digits)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1717 次 |
最近记录: |