Что такое эквивалент 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);