IgnoreCase 与 ToUpper/ToLower 数据库查询

IgnoreCase vs ToUpper/ToLower Database Query

我将用户名存储在我的数据库中,但希望保留用户名大小写,以便用户可以拥有诸如 "FooBAR".
之类的用户名 我也希望用户名是唯一的(不管大小写)——"BaR" 会导致 "bar" 不可用。

我看到了三种方法:

首先,我可以像这样查询我的用户 table:

bool usernameAvailable = !_context.Users.Any(u => String.Equals(u.Username, username, StringComparison.OrdinalIgnoreCase));

其次,我可以像这样将两个用户名都转换为大用户名或小用户名:

username = username.ToUpper();
bool usernameAvailable = !_context.Users.Any(u => u.Username.ToUpper() == username);

第三,我可以在我的 table 中创建第二列来存储用户名的 upper/lowercase 版本:

username = username.ToUpper();
bool usernameAvailable = !_context.Users.Any(u => u.UsernameUpper == username);

这将需要更多 space 数据库,但最容易查询。

如有任何见解,我们将不胜感激。

这几乎肯定已经在之前得到了回答,所以请指出我之前任何帖子的方向,因为我找不到我要找的东西。

这取决于你的优先级是什么,你的应用程序应该快速还是使用较少的数据库space,我认为这里的时间差异可以忽略不计,你应该使用第一种方法。

维基百科上有一篇关于这种困境的文章https://en.wikipedia.org/wiki/Space%E2%80%93time_tradeoff

两者都不是一个好的选择。这个问题与数据库端的简单 UNIQUE INDEX 以及用户名列上不区分大小写的 COLLATION 完美匹配。因此,客户端只需要做一个简单的相等性检查,数据库将使用索引来查找是否存在匹配的名称,如果需要,包括不区分大小写的检查

请考虑在添加新用户(检查重复项)以及用户尝试登录时(检查帐户是否存在)时需要进行此类检查。在这两种情况下,索引都可确保用户名所需的唯一性并加快查询速度。

对于 SQLite 的特殊情况,可以像这样创建不区分大小写的唯一索引:

CREATE TABLE users (
    UserName TEXT
    /*Other columns go here*/
    UNIQUE (UserName COLLATE NOCASE)
)

除了加快检索速度之外,这将防止添加两个仅大小写不同的用户名。在客户端,不要理会外壳。当用户登录时,只要做一个正常的比较,即使只是大小写不同,DB 也会匹配他们。对于注册,立即执行 INSERT,如果大小写不同,数据库将崩溃并拒绝它,您可以从那里向用户显示一条 "username already taken" 消息。

另请参阅此 post(我从那里获取基本思想):