Comments 10
Индексы не работают с регулярными выражениями
А если написать
SELECT REGEXP_SUBSTR(...) from sometable
WHERE REGEXP_SUBSTR(...) = somevalue
и на sometable
накинуть соответствующий функциональный индекс?
Доброго времени суток! Спасибо за ваш комментарий и сразу скажу, что вы правы, но с несколькими оговорками:
1) Функция должна быть IMMUTABLE
2) Шаблон в запросе должен точно совпадать с шаблоном в индексе.
Иначе работать не будет:(
В целом предложенный вами вариант - это узкоспециализированное решение для случая, когда нужно часто искать по строго определённому и неизменному шаблону. Для большинства других сценариев эффективнее использовать триграммные индексы.
p.s. Дополню комментарий для большей ясности REGEXP_SUBSTR()
по умолчанию — STABLE
. Так что нужно будет использовать какую-то обёртку.
С регулярными выражениями главное - вовремя остановиться. А так местами даже интересно.
Если в регулярном выражении POSIX имеется ошибка синтаксиса, запрос завершится ошибкой. Особенно это мешает, если выражение извлекается из таблицы в БД, куда пользователь может сохранить что угодно. Это, конечно решается разного рода административными и программными мерами вроде проверки выражения на корректность при вводе пользователем. Но тем не менее случается всякое, а потому есть вопрос. Точнее два.
Первый. Как наименее накладно проверить корректность регулярного выражения? Встречал разные варианты, вплоть до выполнения простого запроса с ним с проверкой успешности выполнения запроса.
Второй. Как заставить PostgreSQL считать при выполнении запроса некорректные регулярные выражения просто не соответствующими ничему вместо завершения с ошибкой? Не встречал вариантов решения вообще.
SELECT
*
FROM
Student
WHERE
birth_date::
TEXT
SIMILAR TO '200-%';
Здесь должно быть 2001 или я чего-то не понимаю?
-- Извлечь первое вхождение трёх последовательных цифр из телефонного номера
SELECT
REGEXP_SUBSTR('800-555-1212', '', 1, 1);
А где в этом коде что-то про три цифры?
Как только речь заходит о сравнении строк, сразу возникает вопрос, какой набор правил, прозываемый COLLATION, будет использоваться. Вы про регистрозависимость уже сказали, правда только для пары LIKE/ILIKE, а что с остальными функциями? как регулировать collation? Что делать, если мне нужно, или наоборот, не нужно, при сравнении игнорировать акценты, смайлики и прочие умляуты? Допустим, у меня есть именно требуемый COLLATION (устраивает какой-то из штатных или определён свой) - где именно его указывать в каждом конкретном случае? только для тестируемой строки? паттерна? и там и там? хоть где-нибудь?
При работе с мультиязычными данными это достаточно важный момент. И он совершенно не освещён.
UPDATE
contacts
SET
phone_number = '+7' || REGEXP_REPLACE(phone_number, '\D', '')
WHERE
REGEXP_LIKE(phone_number, '^\+?7?\d{10}$');
А что если номер уже начинается с +7 ?
Регулярные выражения в PostgreSQL