Что такое эквивалент regexp SUBSTR в mysql?

Я хочу извлечь слово из строкового столбца таблицы.

description
===========================
abc order_id: 2 xxxx yyy aa
mmm order_id: 3 nn kk yw

ожидаемый результат набор

order_id
===========================
2
3

таблица будет иметь не более 100 строк, длина текста составляет ~256 символов, а столбец всегда имеет один order_id настоящее время. Поэтому производительность не проблема.

в Oracle, я могу использовать REGEXP_SUBSTR этой проблемы. Как бы я решил это в MySQL?

изменить 1

Я использую LOCATE и SUBSTR для решения проблемы. Код уродливый. Через десять минут после написания кода я проклинаю парня, который написал такой уродливый код.

Я не нашел функцию REGEXP_SUBSTR в документах MySQL. Но я надеюсь, что она существует..

ответ на : Почему таблица не может быть оптимизирована? Почему данные хранятся в таком тупом виде?

пример я просто обозначает проблему я пытаюсь решить. В реальном сценарии я использую стороннее программное обеспечение очереди на основе БД для выполнения асинхронных задач. Этот очередь сериализует объект Ruby как текст. Я не контролирую структуру таблицы или формат данных. Задачи в очереди могут быть повторяющимися. В нашей тестовой установке некоторые повторяющиеся задачи не выполняются из-за устаревших данных. Я должен удалить эти задачи, чтобы предотвратить ошибку. Такие ошибки не распространены, поэтому я не хочу поддерживать нормализованную теневую таблицу.

4 ответов


"Я не нашел REGEXP_SUBSTR функция в документах MySQL. Но я надеюсь, что она существует.."

да, начиная с MySQL 8.0 он поддерживается. Регулярные Выражения:

REGEXP_SUBSTR(expr, pat[, pos[, occurrence[, match_type]]])

возвращает подстроку строки expr, которая соответствует регулярному выражению, указанному шаблоном pat, NULL, если нет соответствия. Если expr или pat равно NULL, возвращаемое значение равно NULL.


Как сказал Конерак, в MySql нет эквивалента REGEXP_SUBSTR. Вы можете делать то, что вам нужно, используя логику подстроки, но это уродливо :

SELECT
  SUBSTRING(lastPart.end, 1, LOCATE(' ', lastPart.end) - 1) AS orderId
FROM
  (
    SELECT
      SUBSTRING(dataset.description, LOCATE('order_id: ', dataset.description) + LENGTH('order_id: ')) AS end
    FROM
      (
        SELECT 'abc order_id: 2 xxxx yyy aa' AS description
        UNION SELECT 'mmm order_id: 3 nn kk yw' AS description
        UNION SELECT 'mmm order_id: 1523 nn kk yw' AS description
      ) AS dataset
    ) AS lastPart

Edit: вы можете попробовать это пользовательская функция предоставление доступа к Perl regex в MySql

SELECT 
  PREG_CAPTURE( '/.*order_id:\s(\d+).*/', dataset.description,1)
FROM
  (
    SELECT 'abc order_id: 2 xxxx yyy aa' AS description
    UNION SELECT 'mmm order_id: 3 nn kk yw' AS description
    UNION SELECT 'mmm order_id: 1523 nn kk yw' AS description
  ) AS dataset

нет эквивалента MySQL. Регулярное выражение MySQL может использоваться для сопоставления строк, но не для их преобразования.

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

а вы уверены, что ваш формат данных и выбрал? Если вам нужен order_id, не имеет смысла хранить его в другом столбце, чтобы вы могли поместить индексы, использовать соединения и нравится?


или вы можете сделать это и спасти себя уродство :

select SUBSTRING_INDEX(SUBSTRING_INDEX('habc order_id: 2 xxxx yyy aa',' ',3),' ',-1);