0

我有这个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 转换为浮点数时出错”。第二次*我执行成功 - 因为没有 'qwerty' 或 'zxcvb' shqscriteria,所以不返回任何行

*实际上有时我必须执行多达 8 次才能失败

4

2 回答 2

3

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

所以:

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

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

Also, ISNUMERIC is a mostly useless function. CAST('£' as float) will fail, but ISNUMERIC('£') is 1. It answers the question no-one has ever asked - "Can I convert this string into even just one of the numeric datatypes (I don't care which one)?"

The way to resolve this kind of issue is to split your query into two parts - the first of which selects appropriate data for conversion and stores the values in a (temp table/table variable), the second part actually performs the conversion. Or if you're on SQL Server 2012 or later, look into the TRY_ conversion functions:

c.shqscriteria = 'zxcvb' AND TRY_CAST(sa.answertext AS float) < 5
于 2013-01-31T11:51:53.147 回答
1

As long as you're not using aggregates, you should be able to rely on CASE's order of execution:

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

Note however that ISNUMERIC(col) = 1 does not always mean that col is eligible to be converted to a specific numeric type.

于 2013-01-31T12:25:49.660 回答