Oracle: to_number() в сочетании с substr() и regexp_like() в предложении WHERE

У меня есть таблица со столбцом "описание", который имеет следующие значения:

  • ОПТестМашине
  • OPManualTesting
  • OP1010

Таким образом, оператор select для получения значений будет просто

SELECT description
  FROM operation;

Я хочу извлечь число «1010» (или любую строку, которая соответствует критерию substr()) и преобразовать «найденную строку» в целое число, если это возможно.

Итак, я придумал это:

SELECT to_number(substr(description, 3, 4))
  FROM operation
 WHERE regexp_like(substr(description, 3, 4), '^\d+(\.\d+)?$', '')

Результат простой и понятный: "1010"

Это работает очень хорошо для меня.

Теперь самое сложное для меня: я хочу использовать результат substr() в предложении WHERE.

Что-то вроде этого:

 SELECT to_number(substr(description, 3, 4))
   FROM operation
  WHERE regexp_like(substr(description, 3, 4), '^\d+(\.\d+)?$', '')
    AND substr(description, 3, 4) < 2000;

Когда я это делаю, я получаю сообщение об ошибке «Неверный номер». Я предполагаю, что это из-за того, как сервер анализирует оператор select.

Если бы вы могли оказать какую-либо помощь, это было бы здорово!


person rwur    schedule 27.10.2016    source источник


Ответы (2)


Функция substr возвращает строку, и вы должны явно преобразовать ее в число, как вы делали это в операторе select: AND to_number(substr(description, 3, 4)) < 2000;

person Sebz    schedule 27.10.2016
comment
Извините, но я уже пробовал это, и он возвращает ту же ошибку Неверный номер - person rwur; 27.10.2016
comment
Моя догадка заключается в том, что подстрока возвращает нечто иное, чем число, и это приводит к сбою. Попробуйте обрезать его на случай, если он встретит пробелы: AND to_number(ltrim(rtrim(substr(description, 3, 4)))) < 2000; - person Sebz; 27.10.2016
comment
Да, ты прав! Второе решение с обрезкой работает! - person rwur; 27.10.2016
comment
@rwur trim() - хорошее решение, но я не уверен, что вы можете полагаться на порядок проверки условий. Так что, возможно, добавление другого запроса безопаснее. - person Kacper; 27.10.2016

 SELECT to_number(substr(description, 3, 4))
   FROM operation
  WHERE regexp_like(substr(description, 3, 4), '^\d+(\.\d+)?$', '')
    AND to_number(substr(description, 3, 4)) < 2000;

Второй to_number помогает?

если бы я не сделал:

select to_number(x) from (
SELECT substr(description, 3, 4) x
       FROM operation
      WHERE regexp_like(substr(description, 3, 4), '^\d+(\.\d+)?$', ''))
        WHERE to_number(x) < 2000;
person Kacper    schedule 27.10.2016
comment
Извините, но я уже пробовал это, и он возвращает ту же ошибку Неверный номер - person rwur; 27.10.2016
comment
@rwur тоже второй запрос? В таком случае, какой у вас десятичный разделитель? - person Kacper; 27.10.2016