我想确保当用户想要在我的系统(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
答案 0 :(得分:4)
我这样做的方法是为用户名创建第二列,将其转换为全部大写或全部小写。我把它放在一个独特的索引上。我使用触发器在另一列中生成值,因此代码不必担心它。
想想看,你可以使用基于函数的索引来得到相同的结果:
CREATE UNIQUE INDEX user_name_ui1 ON user(lower(name))
答案 1 :(得分:3)
您假设唯一约束将区分大小写是不正确的。他们将根据列的整理进行比较。所有商业数据库都值得谈论支持整理。只需为列选择不区分大小写的排序规则,并在其上声明唯一约束。参见:
通过查找执行强制执行并在插入之前不仅非常低效,在并发下也是不正确的。
答案 2 :(得分:0)
您还可以通过更改该列的排序规则来更改唯一约束的工作方式:Unique constraint on table column