为什么我的sql逻辑第一次运行但第二次运行失败?

时间:2013-01-31 11:47:26

标签: sql sql-server sql-server-2008

我有这个sql:

SELECT
    sa.answertext
FROM dbo.tblsurveyanswer sa
            INNER JOIN dbo.tblsurvey s
                ON s.surveyid = sa.surveyid
            INNER JOIN dbo.tblquestion q
                ON q.questionid = sa.questionid
            INNER JOIN dbo.tblshqscriteria c
                ON c.shqscriteriaid = q.shqscriteriaid
            INNER JOIN dbo.tblshqsdescription d
                ON d.shqsdescriptionid = q.shqsdescriptionid
            INNER JOIN dbo.tblrepairpercentage rp
                ON rp.repairpercentageid = sa.repairpercentageid
WHERE 
(c.shqscriteria = 'qwerty')
OR 
(c.shqscriteria = 'zxcvb' AND ISNUMERIC(sa.answertext) = 1 AND CAST(sa.answertext AS float) < 5)

我第一次执行它失败,并显示“将数据类型varchar转换为float时出错”。 第二次*我执行成功 - 没有返回任何行,因为没有'qwerty'或'zxcvb'shqscriteria

*实际上有时候我必须在失败前执行最多8次

2 个答案:

答案 0 :(得分:3)

不保证在SQL Server中评估谓词的顺序(当然不能保证从左到右)。

所以:

c.shqscriteria = 'zxcvb' AND ISNUMERIC(sa.answertext) = 1 AND CAST(sa.answertext AS float) < 5

它可能会对CAST返回0的值尝试ISNUMERIC()操作。评估谓词的实际顺序可能因各种原因而有所不同 - 正如您所发现的那样,最轻微的事情可以改变它。

此外,ISNUMERIC是一个无用的功能。 CAST('£' as float)会失败,但ISNUMERIC('£')1。它回答了没有人曾经问过的问题 - “我可以将这个字符串转换成数字数据类型的一个(我不关心哪个)?”

解决此类问题的方法是将查询分为两部分 - 第一部分选择适当的数据进行转换并将值存储在(临时表/表变量)中,第二部分实际执行转换。或者,如果您使用的是SQL Server 2012或更高版本,请查看TRY_ conversion functions

c.shqscriteria = 'zxcvb' AND TRY_CAST(sa.answertext AS float) < 5

答案 1 :(得分:1)

只要您不使用聚合,您就应该能够依赖CASE的执行顺序:

WHERE
...
OR
(
  c.shqscriteria = 'zxcvb' 
  AND 5 > CASE WHEN ISNUMERIC(sa.answertext) = 1      
    THEN CAST(sa.answertext AS float) 
    ELSE 6 
  END
)

但请注意,ISNUMERIC(col) = 1并不总是意味着col有资格转换为特定的数字类型。