我有这个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次
答案 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
有资格转换为特定的数字类型。