Укажите порядок выполнения (T) SQL - PullRequest
1 голос
/ 02 апреля 2011

Я видел похожие вопросы, задаваемые в других местах на этом сайте, но больше в контексте оптимизации.

У меня возникла проблема с порядком выполнения условий в предложении WHERE. У меня есть поле, в котором хранятся коды, большинство из которых являются числовыми, но некоторые содержат нечисловые символы. Мне нужно сделать некоторые операции с числовыми кодами, которые будут вызывать ошибки при попытке не числовых строк. Я пытаюсь сделать что-то вроде

WHERE isnumeric(code) = 1
AND CAST(code AS integer) % 2 = 1

Есть ли способ убедиться, что isnumeric () выполняется первым? Если это не так, я получаю сообщение об ошибке ...

Заранее спасибо!

Ответы [ 4 ]

5 голосов
/ 02 апреля 2011

Гарантирован только порядок оценки CASE

WHERE 
     CASE WHEN isnumeric(code) = 1 
          THEN CAST(code AS integer) % 2 
END = 1

Кроме того, только то, что он проходит тест isnumeric, не гарантирует, что он будет успешно cast в целое число.

 SELECT ISNUMERIC('$') /*Returns 1*/

 SELECT CAST('$' AS INTEGER) /*Fails*/

В зависимости от ваших потребностей вы можете найти эти альтернативы предпочтительнее.

1 голос
/ 02 апреля 2011

Почему бы просто не сделать это с помощью LIKE?:

Where Code Not Like '%[^0-9]%'

Кстати, используя мое решение или IsNumeric, есть некоторые крайние случаи, которые могут привести к использованию UDF, например 1,234,567, где IsNumeric вернет 1, но Cast выдаст исключение.

0 голосов
/ 02 апреля 2011

Вы можете сделать это в операторе case в предложении select, а затем ограничить значением во внешнем select

select * from (    
    select
    case when isNum = 1 then CAST(code AS integer) % 2 else 0 end as castVal
    from (
       select
       Case when isnumeric(code) = 1 then 1 else 0 end as isNum
       from table) t
) t2
where castval = 1
0 голосов
/ 02 апреля 2011

Почему бы не использовать оператор CASE, чтобы сказать что-то вроде:

WHERE 
CASE WHEN isnumeric(code) = 1 
THEN CAST(code AS int) % 2 = 1 
ELSE /* What ever else if not numeric */ END
...