在数据库中保持字符串不区分大小写

时间:2010-12-19 21:31:36

标签: sql database unique case-insensitive

我想确保当用户想要在我的系统(Web应用程序)中注册用户名时,即使不考虑大小写,用户名也是唯一的。因此,如果已注册名为“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 (?, ?, …);

我不确定“for update”是否会将数据库锁定得足够远,以致其他用户无法在上述两个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 个答案:

答案 0 :(得分:4)

我这样做的方法是为用户名创建第二列,将其转换为全部大写或全部小写。我把它放在一个独特的索引上。我使用触发器在另一列中生成值,因此代码不必担心它。

想想看,你可以使用基于函数的索引来得到相同的结果:

CREATE UNIQUE INDEX user_name_ui1 ON user(lower(name))

答案 1 :(得分:3)

您假设唯一约束将区分大小写是不正确的。他们将根据列的整理进行比较。所有商业数据库都值得谈论支持整理。只需为列选择不区分大小写的排序规则,并在其上声明唯一约束。参见:

通过查找执行强制执行并在插入之前不仅非常低效,在并发下也是不正确的。

答案 2 :(得分:0)

您还可以通过更改该列的排序规则来更改唯一约束的工作方式:Unique constraint on table column