2014-08-28 1 views
0

У меня есть база данных, которая использует varchar(255) в качестве заполнителя для хранения множества разных типов данных. Я пытаюсь преобразовать некоторые из этих значений в decimal для численного сравнения.SQL Server: ошибка преобразования типа данных varchar в числовой, если я не использую REPLACE

Если я пытаюсь использовать следующую функцию это приведет к ошибке в названии

ISNUMERIC(Value + 'e0') = 1 and CONVERT(decimal (16,4), Value) < CONVERT(decimal (16,4),11) 

Я думал, что это было странно, так что я переехал CONVERT в отборное заявление, чтобы узнать, есть ли еще какие-то ценности ISNUMERIC не ловил. Там не было. CONVERT выше удалось успешно преобразовать каждый столбец без ошибок.

select CONVERT(decimal (16,4), Value) 

Далее я попробовал обернуть выбор в другом выборе и переместить сравнение в внешний запрос. Это тоже не сработало, а также привело к большому использованию памяти, поэтому я отказался от этой идеи.

Один из моих коллег подумал, что, возможно, была одна строка данных, которая вызывала проблему, и хотя CONVERT на выбор работал хорошо, стоит попробовать только посмотреть. Мы попробовали REPLACE внутри CONVERT, как показано ниже:

ISNUMERIC(Value + 'e0') = 1 and CONVERT(decimal (16,4),REPLACE(Value, 'blah', '')) < CONVERT(decimal (16,4), 11) 

... и как-то это работало. Независимо от того, что мы вводим в замену, он работает отлично. Это явно ничего не заменяет. Я прочитал, что REPLACE усечет очень большие данные (8 000 + байтов), но это varchar(255), и поэтому нет никаких больших данных для обрезания.

Мне больше всего любопытно, почему это работает или есть что-то еще, вероятно, здесь, и REPLACE по совпадению работал? Для меня это не имеет никакого смысла.

Редактировать: Просто, чтобы быть ясным, я застрял в этом проекте базы данных. Я не могу его изменить. Я понимаю, что это ужасный способ хранения данных. Доверьтесь мне.

Редактировать # 2: Я только узнал, что TRY_CONVERT также будет работать. Я думаю, мой оригинальный вопрос все еще стоит. Хотя у меня есть два потенциальных решения, я не понимаю, почему это ломается.

+3

«У меня есть база данных, которая использует varchar (255) в качестве заполнителя для хранения множества разных типов данных». Это неправильный способ обработки данных. Вы должны использовать соответствующие типы данных. Когда вы используете varchar для всего, вы запускаете всевозможные проблемы. Просто не делай этого с собой. –

+0

Не создавал базу данных. Не могу это изменить. Я знаю, как это глупо. – Chase

ответ

5

Предположительно, ваше выражение в предложении where:

where ISNUMERIC(Value + 'e0') = 1 and CONVERT(decimal (16,4), Value) < CONVERT(decimal (16,4),11) 

SQL Server делает не гарантирует порядок оценки стоимости выражений. Итак, вы не знаете, идет ли сначала convert(), или isnumeric(). Для такого выражения в предложении where все базы данных оставляют за собой право оценивать их в любом порядке, который хочет оптимизатор.

Это один случай, когда использование case в статье where выгодно. case действительно имеет некоторые гарантии по порядку оценки.Следующие должны работать:

where (case when ISNUMERIC(Value + 'e0') = 1 
      then CONVERT(decimal(16,4), Value) 
     end) < CONVERT(decimal(16,4), 11) 

второго преобразования является ненужную, на мой взгляд:

where (case when ISNUMERIC(Value + 'e0') = 1 
      then CONVERT(decimal(16,4), Value) 
     end) < 11 

Кстати, использование 'e0' умный способ просто смотреть за действительное, не- экспоненциальные числа.

+0

Я учитывал неопределенный порядок оценки выражения с внутренним/внешним запросом, хотя, по крайней мере, я думаю, что сделал. Я сделал внутренний запрос, который сделал SELECT CONVERT с WHERE ISNUMERIC, а затем выбрал его и сделал то, что на внешнем и применил числовой фильтр. Разве это не сработало? – Chase

+0

@Steven. , , Неа. CTE и подзапросы не влияют на порядок оценки. Гарантируется только «случай» в одном запросе. –

+0

@GordonLinoff. Эта проблема может быть очень уродливой в JOIN, если вы считаете, что не присоединяетесь к недействительным данным, но все равно оценивается, потому что порядок eval не гарантируется и оптимизирован для другого потока. – Hogan

Смежные вопросы