sql - 使字符串在数据库中保持不区分大小写的唯一性

标签 sql database unique case-insensitive

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

我不确定“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

最佳答案

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

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

在用户 (lower(name)) 上创建唯一索引 user_name_ui1

关于sql - 使字符串在数据库中保持不区分大小写的唯一性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4485221/

相关文章:

database - 循环或输出中的最后和第一个内容(冷融合)

mysql - 如何将我的表名告诉 laravel5 auth Controller ?

mysql - 与两个实体共享地址表是一个好习惯吗?

mongodb - 在 Mongodb 中,如何检查所有文档的值是否都是唯一的?

mysql - SQL : Ideal engine type (MyISAM vs InnoDB) and data type for unique text column

php - 插入时返回 MySQL 时间戳

mysql - 获取一个表中的记录,排除另一表中的记录

php - 注册后自动登录

mysql - 如何在mysql数据库中创建随机唯一(不重复)和固定长度(9位)主键?

mysql使用来自另一个表的关系从表中订购数据