PostgreSQL: уникальный email без учёта регистра

Категория: Postgresql · Язык: SQL · Обновлено:

Обычное UNIQUE для text различает регистр. Создайте функциональный unique index по lower(email), чтобы база запрещала Anna@example.com и anna@example.com как один адрес. ??????? ????????? ?????? ?? ????????? ??????? ? ??????? ???? ?????????? ?? ????? ??????.

Рабочий пример

SQL
CREATE TEMP TABLE users(email text);
CREATE UNIQUE INDEX users_email_lower_uq ON users (lower(email));
INSERT INTO users VALUES ('Anna@example.com');
INSERT INTO users VALUES ('boris@example.com');
SELECT lower(email) AS normalized FROM users ORDER BY normalized;

Индекс нужен для фактического инварианта уникальности, а не только для ускорения SELECT. Для Unicode правила регистра зависят от collation и версии, поэтому проверьте нужную локаль.

Частый вопрос

Подойдёт ли тип citext?

citext упрощает case-insensitive сравнения, но зависит от расширения и collation. Функциональный индекс явно задаёт правило и подходит, если оно ограничено конкретной колонкой.