[英]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.