下面的查询意外失败,出现算术溢出错误.
select IsNull(t2.val, 5005)
from(
SELECT 336.6 as val UNION ALL
SELECT NULL
) as t2
Run Code Online (Sandbox Code Playgroud)
"将int转换为数据类型numeric的算术溢出错误."
奇怪的是,如果修改查询以删除NULL并将其替换为与null coalesce(5005)中相同的值,则它会运行而没有问题
select IsNull(t2.val, 5005)
from(
SELECT 336.6 as val UNION ALL
SELECT 5005
) as t2
Run Code Online (Sandbox Code Playgroud)
另外,省略SELECT NULL行完全允许查询无问题地运行
select IsNull(t2.val, 5005)
from(
SELECT 336.6 as val
) as t2
Run Code Online (Sandbox Code Playgroud)
如果IsNull函数中的coalesce值更改为一个小于足以在子查询中转换为十进制而不加宽的整数,则查询将运行
select IsNull(t2.val, 500)
from(
SELECT 336.6 as val UNION ALL
SELECT NULL
) as t2
Run Code Online (Sandbox Code Playgroud)
在SQL Server 2005和SQL Server 2008中都进行了测试.
通常将整数与小数组合是无缝的,SQL Server会将整数和小数转换为足以容纳两者的十进制类型.但由于某种原因,运行查询,其中从UNION和IsNull都发生转换,导致转换失败.
有人知道为什么吗?
试试这个
select * into t2
from(
SELECT 336.6 as val
UNION ALL
SELECT NULL
) as x
Run Code Online (Sandbox Code Playgroud)
如果现在查看列,则会看到数字精度为4且比例为1的数字
select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='T2'
Run Code Online (Sandbox Code Playgroud)
SQL根据最小的数字精度做出决定,以保持336.6.现在,当你要求它将NULL转换为5005时,你要说的是,将任何NULL值转换为一个太大而不适合数字的数字,精度为4,比例为1.错误信息表示5005韩元'适合数字(4,1)
这将工作,因为表现在产生一个更大的数字字段,因为SQL需要适应5005采用T2的新内容,从下创建表,字段类型应该去数字(5,1),允许5005适合.
select IsNull(t2.val, 5005)
from(
SELECT 336.6 as val UNION ALL
SELECT 5005
) as t2
Run Code Online (Sandbox Code Playgroud)
当您在内部查询中运行没有NULL的语句时,SQL从不评估5005,因此它不会达到需要将5005放入数字(4,1)字段的条件.
select IsNull(t2.val, 5005)
from(
SELECT 336.6 as val
) as t2
Run Code Online (Sandbox Code Playgroud)
我认为问题是当SQL Server解析联合时,它决定一个只有大到足以适合333.6(即decimal(4,1))的十进制类型.试图将5005放入其中会导致溢出.
您可以自己解决指定十进制精度的问题:
select IsNull(t2.val, 5005)
from(
SELECT CONVERT(DECIMAL(5,1), 336.6) as val UNION ALL
SELECT NULL
) as t2
Run Code Online (Sandbox Code Playgroud)