日期:2014-05-16  浏览次数:20633 次

一个“神奇”的查询出错
SELECT * FROM (SELECT CAST(RIGHT(f1,4) AS INT) AS f FROM Table1 WHERE a=b) t WHERE f>0

其中子句t:SELECT CAST(RIGHT(f1,4) AS INT) AS f FROM Table1 WHERE a=b,查询正常,
但象上面那样完整查询,就会报错:在将 nvarchar 值 '90)' 转换成数据类型 int 时失败。
依据提示来看,这个')90'就在列f里面,但实际上,')90'这个结果只存在于Table1整个表中,当加上条件a=b后就绝对不存在了,
那为什么还有这样的提示呢?非常不解啊。
------解决方案--------------------
换CTE试试,根据我了解,好像是因为优化器改写了你的查询,导致先读取了那些你以为已经过滤掉的数据
------解决方案--------------------
见过这种情况,但是也没找到权威说法
------解决方案--------------------
如果用子查询的方法:
with table1 as(
select ')90' as f1,1 as a,2 as b union all
select '90' as f1,1 as a,1 as b)
SELECT * from 
(select CAST(RIGHT(f1,4) AS INT) as f
FROM table1 
where case when a=b then 1 else 0 end=1) t
where f>0;

也是不行的,是因为经过SQLServer改写后的谓词逻辑变成了:
where CAST(RIGHT(f1,4) AS INT)>0 and case....
只有把case语句显式的写在最前面才可以避免这个问题:
where case when a=b then 1 else 0 end=1 and CAST(RIGHT(f1,4) AS INT)>0