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

ygo*_*goe 2 sql database unique case-insensitive

我想确保当用户想要在我的系统(Web 应用程序)中注册用户名时,即使不考虑大小写,用户名也是唯一的。因此,如果名为“SuperMan”的用户已经注册,则不得允许其他用户注册为“superman”或“SUPERman”。必须在数据库级别检查这一点。

\n\n

在我当前的实现中,我执行以下操作:

\n\n
\nselect count(*) from user where lower(name) = lower(?) for update;\n-- 如果计数大于 0,则错误中止\n-- 确定用户的新 ID\n插入转换为用户 (id, name, \xe2\x80\xa6) 值 (?, ?, \xe2\x80\xa6);\n
\n\n

我不确定“for update”是否会将数据库锁定得足够远,以便其他用户无法使用上述两个 SQL 语句之间的无效名称进行注册。可能这不是 100% 安全的解决方案。不幸的是我不能在 SQL 中使用唯一键,因为它们只会区分大小写进行比较。

\n\n

还有其他解决方案吗?为了增加更多的安全性,下面的怎么样?

\n\n
\nselect count(*) from user where lower(name) = lower(?) for update;\n-- 如果计数大于 0,则错误中止\n-- 确定用户的新 ID\n插入进入用户 (id, name, \xe2\x80\xa6) 值 (?, ?, \xe2\x80\xa6);\n-- 现在再次计数\n从用户中选择 count(*),其中 lower(name) = lower (?);\n-- 如果计数现在大于 1,请执行以下操作:\n从 id = ? 的用户中删除;\n-- 或者回滚事务\n
\n

JOT*_*OTN 5

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

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

创建唯一索引 user_name_ui1 ON user (lower(name))