IsNumeric в SQL Server ПРИСОЕДИНЯЙТЕСЬ - PullRequest
3 голосов
/ 17 января 2012

Моя проблема, кажется, очень проста, но я застрял здесь.У меня есть таблица, в которой есть столбец «nvarchar» под названием «SrcID», и я храню в нем как числа, так и строки.Теперь, когда я пытаюсь проверить «IsNumeric» для этого столбца в состоянии «Join», что-то вроде ниже,

   ISNUMERIC(SrcID) = 1 AND SrcID > 15

, я получаю следующую ошибку:

  Msg 245, Level 16, State 1, Line 47
  Conversion failed when converting the nvarchar value 'Test' to data type int.

Удивительно, но когда я убираю флажок «SrcID> 15», мой запрос выполняется правильно.Должен ли я включить что-нибудь еще в это заявление?

Пожалуйста, помогите мне решить проблему.Заранее спасибо !!

Ответы [ 2 ]

3 голосов
/ 17 января 2012

Вы не можете рассчитывать на порядок, в котором база данных будет оценивать выражения фильтрации. Существует оптимизатор запросов, который оценит ваш запрос и создаст план для его выполнения на основе наилучшей производительности . Выражение SrcID > 15 может быть сопоставлено с индексом, но IsNumeric(SrcID) = 1 не может быть сопоставлено с индексом, и поэтому SrcID > 15, скорее всего, будет оцениваться в первую очередь, потому что оно помогает отфильтровать больше потенциальных записи быстрее.

Скорее всего, вы можете обойти это с помощью представления, подзапроса, CTE, оператора CASE или вычисляемого столбца. Вот пример CTE:

With NumericOnly As 
(
    SELECT <columns> FROM MyTable WHERE IsNumeric(SrcID) = 1
)
SELECT <columns> FROM NumericOnly WHERE SrcID > 15

А вот опция оператора CASE:

SELECT <columns> FROM MyTable WHERE CASE WHEN IsNumeric(SrcIC) = 1 THEN Cast(SrcID As Int) ELSE 0 END > 15
2 голосов
/ 17 января 2012

Фильтры в предложении WHERE не оцениваются ни в каком конкретном порядке.

Это распространенное заблуждение в SQL Server - оптимизатор проверит, какие условия он считает наиболее быстрым / простым, и попытается ограничить данные наиболее эффективным способом.

В вашем примере у вас, вероятно, есть индекс на SrcID, и оптимизатор считает, что ПЕРВЫМ будет быстрее ограничить результаты значением, равным SrcID > 15, затем запустите функцию на всех этих строках (так как функция будет в противном случае необходимо проверить каждую строку).

Вы можете попытаться задать порядок операций с круглыми скобками, например:

WHERE (ISNUMERIC(SrcID) = 1) AND SrcID > 15

Или с указанием регистра:

WHERE CASE WHEN ISNUMERIC(SrcID) = 1 THEN SrcID > 15 ELSE 1=0 END

...