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 から float への変換エラー」で失敗します。2回目*実行すると成功します-「qwerty」または「zxcvb」shqscriteriaがないため、行が返されません

*実際には、失敗する前に実行を最大 8 回ヒットする必要がある場合があります

4

2 に答える 2

3

The order in which predicates are evaluated in SQL Server is not guaranteed (and certainly not guaranteed to be from left to right).

So:

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

It may attempt the CAST operation on a value for which ISNUMERIC() returns 0. The actual order in which the predicates are evaluated can vary for many different reasons - as you've discovered, the slightest thing can change it.

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

アグリゲートを使用していない限り、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

于 2013-01-31T12:25:49.660 に答える