以下查询意外失败,出现算术溢出错误。
select IsNull(t2.val, 5005)
from(
SELECT 336.6 as val UNION ALL
SELECT NULL
) as t2
"将int转换为数据类型numeric的算术溢出错误。"
奇怪的是,如果修改查询以删除NULL并将其替换为与null coalesce(5005)中相同的值,则它将无问题地运行
select IsNull(t2.val, 5005)
from(
SELECT 336.6 as val UNION ALL
SELECT 5005
) as t2
此外,省略SELECT NULL行完全允许查询无问题地运行
select IsNull(t2.val, 5005)
from(
SELECT 336.6 as val
) as t2
如果IsNull函数中的coalesce值更改为一个小于足以在子查询中转换为十进制而不加宽的整数,则运行查询
select IsNull(t2.val, 500)
from(
SELECT 336.6 as val UNION ALL
SELECT NULL
) as t2
在SQL Server 2005和SQL Server 2008中都进行了测试。
通常将整数与小数组合是无缝的,SQL Server会将整数和小数转换为足以容纳两者的十进制类型。但由于某种原因,运行一个查询,其中从UNION和IsNull发生转换,导致转换失败。
有谁知道这是为什么?
答案 0 :(得分:6)
尝试这样做
select * into t2
from(
SELECT 336.6 as val
UNION ALL
SELECT NULL
) as x
如果现在查看列,您会看到数字精度为4且比例为1
的数字select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='T2'
SQL根据最小的数字精度做出了这个决定,以保持336.6。现在,当你要求它将NULL转换为5005时,你要说的是,将任何NULL值转换为一个太大而不适合数字的数字,精度为4,比例为1.错误信息表示5005韩元' t适合数字(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
当你在内部查询中运行没有NULL的语句时,SQL从不评估5005,因此它不会达到需要将5005放入数字(4,1)字段的条件。
select IsNull(t2.val, 5005)
from(
SELECT 336.6 as val
) as t2
答案 1 :(得分:5)
我认为问题是当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
答案 2 :(得分:0)
我相信它是因为您的336.6值被推断为数据类型为NUMERIC。如果你想更具体,那么明确将它转换为DECIMAL;
SELECT IsNull(t2.val, CAST(5005 AS DECIMAL))
FROM (
SELECT CAST(336.6 AS DECIMAL) AS val
UNION ALL
SELECT NULL
) AS t2