繁体   English   中英

Postgres中不区分大小写

[英]Case insensitive in Postgres

我目前正在做一个Java项目,该项目已经开发了几个月。 该项目即将完成,现在我意识到Postgres是区分大小写的。

在我的登录过程中,无法区分username和“ UserName”。 我正在使用Java base,Hibernate和JPA作为后端实现,并使用Postgres作为数据库。

我一直在互联网上寻找解决方案,而得到的大多数答案都建议我使用解决方案:

select loginId from user where 
lower(loginId)=loginid.toLowerCase();

或将表列的数据类型更改为citext。

但是,有没有更快的方法呢? 或者,也许Postgres.conf有任何变量能够控制不区分大小写的变量? 还是在休眠状态下我可以轻松控制它?

我知道使用方法lower(loginId)=loginId.toLowerCase()是解决问题的最简单方法,但是我的项目中需要更改很多代码,这可能需要很长时间才能解决。 对于早已实施的项目,将数据类型更改为citext并不是一个好的解决方案。

这里有没有人有更好的解决方案来解决我当前的问题?

PostgreSQL在全局范围内或在每个列/运算符的基础上没有区分大小写的排序规则 它也没有“区分大小写”配置选项。

您的选择是:

  • 使用citext你想区分insitive的cols类型。 如果列始终不区分大小写,则可能是最佳选择; 除非Hibernate遇到问题,否则我将这样做。 重要的是, citext 不区分大小写 ,即保持大小写 ,即在比较中不认为它们是重要的。

  • 显式比较小写值,每个lower(col) = lower('Literal') 无法在col上使用索引,必须在lower(col)上创建一个单独的索引。 col唯一约束(包括主键)不会区分大小写; 如果需要,您必须在lower(col)上创建一个唯一索引。 这种方法是保持大小写的。

  • col上添加CHECK约束,该约束仅允许小写的值而拒绝大写的值。 您可以将其与BEFORE INSERT OR UPDATE ... FOR EACH ROW触发器结合使用,如果需要,可以使用小写输入。 这样,列的值只能是小写。 然后,只需确保客户端应用程序始终将小写的值进行比较即可。 这种方法不保留大小写 -当您输入BOB ,数据库存储bob并且以后无法知道输入了哪个。

  • 由于您使用的是ORM,因此您可以在模型代码中执行下壳体。 只要让您的实体始终在访问器上降低toLowerCase输入和输出即可。 您仍然需要记住在代码中将小写的比较的其他值小写,但是它不那么脆弱。 同样,这不是大小写保留的。

就个人而言,我只在适当的地方使用citext,这就是它的用途。

只能在initdb时对PostgreSQL中的大小写敏感度进行全局切换-否则,打开或关闭大小写敏感度会突然使先前有效的唯一约束违反,先前有效的外键约束遭到违反,中断检查约束等。这也违反了SQL标准,要求区分大小写。 因此PostgreSQL不支持它。

如果按列和按运算符排序规则覆盖支持的不区分大小写的排序规则, 很有用。 但是,他们没有。

您可以尝试一下,看看它是否适合您。 我建议将其用作临时文件,直到修复程序为止。

SELECT loginID 
FROM user 
WHERE (SELECT CHAR_LENGTH(REGEXP_REPLACE(loginId,*loginId from java*,'','ig')) = 0)

如果loginID匹配而不检查是否区分大小写,则应该为您提供loginID。 另外,如果您拥有多个相同登录名但大小写不同的登录名,那么这将对您不起作用。

这是使用数据库中的测试表之一进行输出的示例。 用户名在我的表中全部大写。

select username from test.person where (select char_length(regexp_replace(username,'jMeRlOs','', 'ig')) = 0)

结果: 在此处输入图片说明

您有正确的想法,只需要在Lower(loginId)上基于表达式的索引。 看到

http://www.postgresql.org/docs/9.1/static/indexes-expressional.html

有关基于表达式的索引的详细信息。 对于您的情况,您将需要创建:

CREATE INDEX tablename_lower_loginId_idx ON表名(lower(loginId));

如果您已经拥有不执行此操作的代码,则可以重命名表并创建视图。 然后,您的代码将从视图中读出,但是您仍然必须更改要写入的表的名称。

还有一点要注意:对于loginId,最好还是先存储小写值,如另一个答案中所述。 也许您可以创建一个新列,然后将所有小写的loginId复制到新列中,然后设置一个约束以确保没有新的无效条目进入。然后用新列替换旧列,并确保只传递较低的列到后端的大小写值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM