为什么此SQL查询失败

Tre*_*ent 2 sql sql-server

下面的查询意外失败,出现算术溢出错误.

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都发生转换,导致转换失败.

有人知道为什么吗?

Spa*_*rky 6

试试这个

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)


Szy*_*mon 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
Run Code Online (Sandbox Code Playgroud)