All streams
Search
Write a publication
Pull to refresh

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 или я чего-то не понимаю?

Вероятно '200[0-2]%'; исходя из комментария "Найти студентов, родившихся между 2000 и 2002 годами"

-- Извлечь первое вхождение трёх последовательных цифр из телефонного номера

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 ?

Sign up to leave a comment.

Articles