Сохранять строки без учета регистра в базе данных - PullRequest
1 голос
/ 20 декабря 2010

Я хотел бы убедиться, что когда пользователь хочет зарегистрировать имя пользователя в моей системе (веб-приложение), имя пользователя является уникальным, даже если регистр не рассматривается.Поэтому, если пользователь с именем «SuperMan» уже зарегистрирован, ни одному другому пользователю не должно быть разрешено регистрироваться как «superman» или «SUPERman».Это должно быть проверено на уровне базы данных.

В моей текущей реализации я делаю следующее:

select count(*) from user where lower(name) = lower(?) for update;
-- If the count is greater than 0, abort with an error
-- Determine a new ID for the user
insert into user (id, name, …) values (?, ?, …);

Я не уверен, будет ли «для обновления» блокировать базу данных достаточно далекотак что другие пользователи не смогут зарегистрироваться с недопустимым именем между двумя операторами SQL выше.Вероятно, это не 100% безопасное решение.К сожалению, я не могу использовать уникальные ключи в SQL, потому что они будут сравниваться только с учетом регистра.

Есть ли другое решение для этого?Как насчет следующего, чтобы добавить больше безопасности?

select count(*) from user where lower(name) = lower(?) for update;
-- If the count is greater than 0, abort with an error
-- Determine a new ID for the user
insert into user (id, name, …) values (?, ?, …);
-- Now count again
select count(*) from user where lower(name) = lower(?);
-- If the count is now greater than 1, do the following:
delete from user where id = ?;
-- Or alternatively roll back the transaction

Ответы [ 3 ]

4 голосов
/ 20 декабря 2010

То, как я это сделал, это создать второй столбец для имени пользователя, которое либо конвертируется во все прописные, либо во все строчные буквы.Это я поставил уникальный индекс на это.Я использую триггер для генерации значения в этом другом столбце, чтобы код не беспокоился об этом.

Если подумать, вы можете использовать индекс на основе функций, чтобы получить тот же результат:

CREATE UNIQUE INDEX user_name_ui1 ON пользователь (нижний (имя))

3 голосов
/ 20 декабря 2010

Ваше предположение, что уникальное ограничение будет сравнивать регистр, неверно.Они будут сравниваться в соответствии с сопоставлением столбца.Все коммерческие базы данных стоит говорить о поддержке сортировки.Просто выберите для вашего столбца сортировку без учета регистра и объявите для нее уникальное ограничение.См .:

Выполнение принудительного поиска путем поиска и перед вставкойне только крайне неэффективен, но и некорректен при одновременном использовании.

0 голосов
/ 20 декабря 2010

Вы также можете изменить способ работы уникальных ограничений, изменив параметры сортировки для этого столбца: Уникальное ограничение для столбца таблицы

...