ChatGPT解决这个技术问题 Extra ChatGPT

如何在 Postgresql 中进行“不区分大小写”的查询?

有什么方法可以在 PostgreSQL 中编写不区分大小写的查询,例如我希望以下 3 个查询返回相同的结果。

SELECT id FROM groups where name='administrator'

SELECT id FROM groups where name='ADMINISTRATOR'

SELECT id FROM groups where name='Administrator'
如果 citext 随您的 Postgres 安装一起提供,请尝试 citext 类型。这是不区分大小写的文本
对于这个问题的新手,postgres 官方文档的 this link 包含此处给出的所有答案,以及一些其他选项。
先生,请为@Arun 所做的重新分配接受的答案。它不那么复杂,并且在申请后不会带来一堆麻烦。

C
Chandu

在比较之前使用 LOWER 函数将字符串转换为小写。

尝试这个:

SELECT id 
  FROM groups
 WHERE LOWER(name)=LOWER('Administrator')

需要注意的是,在谓词列上使用 LOWER(或任何函数)——在本例中为“名称”——将导致任何索引不再可搜索。如果这是一个大的或经常查询的表,那可能会引起麻烦。不区分大小写的排序规则、citext 或基于函数的索引将提高性能。
或者像这样创建一个索引: CREATE INDEX idx_groups_name ON groups lower(name);
如果您希望索引与 LIKE 'xxx%' 查询(即 CREATE INDEX ix_groups_name ON groups (lower(name) varchar_pattern_ops))一起使用,还要指定 varchar_pattern_ops
使用 ILIKE 运算符(如下面的其他答案所示)是一种更简单的方法,即使这是投票最多的答案。
通过这里的评论,这里有很多建议建议ILIKE,它会起作用,but with slow response。为了根据计算结果快速访问表,我建议任何只是检查这个的人都应该接受接受的答案。查看更多详细信息 herehere
M
Matthew Lock

使用 ILIKE 而不是 LIKE

SELECT id FROM groups WHERE name ILIKE 'Administrator'

请注意,在 Spring Boot 中使用时,Hibernate 不支持 ILIKE
@AnT 它适用于 org.hibernate.dialect.PostgreSQL94Dialect 和 Spring Boot 2.0.6.RELEASE。但是 IntelliJ 抱怨它。
ilike 会慢很多吗?特别是当字段被索引时?
M
Mike Sherrill 'Cat Recall'

最常见的方法是将搜索字符串和数据小写或大写。但这样做有两个问题。

它适用于英语,但并非适用于所有语言。 (可能甚至在大多数语言中都没有。)不是每个小写字母都有对应的大写字母。不是每个大写字母都有对应的小写字母。使用像 lower() 和 upper() 这样的函数会给你一个顺序扫描。它不能使用索引。在我的测试系统上,使用 lower() 比使用索引的查询要长约 2000 倍。 (测试数据有超过 100k 行。)

至少有三种不太常用的解决方案可能更有效。

使用 citext 模块,它主要模仿不区分大小写的数据类型的行为。加载该模块后,您可以通过 CREATE INDEX ON groups (name::citext); 创建一个不区分大小写的索引。 (但见下文。)使用不区分大小写的排序规则。这是在初始化数据库时设置的。使用不区分大小写的排序规则意味着您可以接受来自客户端代码的几乎任何格式,并且您仍然会返回有用的结果。 (这也意味着您不能进行区分大小写的查询。Duh。)创建一个功能索引。使用 CREATE INDEX ON groups (LOWER(name)); 创建小写索引。完成此操作后,您可以通过 SELECT id FROM groups WHERE LOWER(name) = LOWER('ADMINISTRATOR'); 或 SELECT id FROM groups WHERE LOWER(name) = 'administrator'; 之类的查询来利用索引。不过,您必须记住使用 LOWER()。

citext 模块不提供真正的不区分大小写的数据类型。相反,它的行为就像每个字符串都是小写的。也就是说,它的行为就像您在每个字符串上调用了 lower() 一样,如上面的数字 3 所示。优点是程序员不必记住小写字符串。但是在决定使用 citext 之前,您需要阅读文档中的“字符串比较行为”和“限制”部分。


关于#1:这应该不是问题,因为它会是两个不同的字符串(把它想象成 col = 'a'col = 'b')。关于#2:正如您所说,您可以在表达式上创建索引,所以这不是一个真正的问题。但我同意你的观点,改变排序规则很可能是最好的解决方案。
有人能告诉我 PostgreSQL 内置排序规则是什么不区分大小写的排序规则吗?我认为这是一个选项,但在网上找不到关于 Postgres 不区分大小写的排序规则的任何信息?
@AnupShah:不,我不是这么说的。我没有在 Windows 上运行 PostgreSQL。 The 9.4 docs say this:“在所有平台上,命名为 default、C 和 POSIX 的排序规则都可用。其他排序规则可能可用,具体取决于操作系统支持。”您可以查看 PostgreSQL 认为哪些排序规则可用于 select * from pg_collation;
@Matthieu:这是对我所知道的主题的最佳介绍(和警告):Edge Cases to Keep in Mind. Part 1 – Text
@Matthieu:The Unicode FAQ 读起来也很有趣。这是Why's there no unique uppercase character for . . .
M
Matthieu

您可以使用 ILIKE。 IE

SELECT id FROM groups where name ILIKE 'administrator'

它对我来说正确且工作正常,我使用的是 MAC OS X(Mountain Lion)。
这将起作用,但响应缓慢。为了根据计算结果快速访问表,我建议使用 lower 函数。查看更多details
@AfolabiOlaoluwaAkinwumi 从根本上说,这归结为您是否在搜索与过滤已知值相反的结果。在后一种情况下,应在数据级别保留一个统一的情况,以允许相等运算符工作。 [个人建议类型代码值的大写帕斯卡]
b
biegleux

您还可以阅读 ILIKE 关键字。它有时会非常有用,尽管它不符合 SQL 标准。有关详细信息,请参见此处:http://www.postgresql.org/docs/9.2/static/functions-matching.html


这里需要注意的是恶意用户输入。如果您运行类似 email ILIKE 'user-input-email-here' 的查询,请确保转义用户输入。否则,人们可以输入匹配任何内容的字符,例如 %。
@MattDeLeon 嗨。说得好。但我只想问你,如果我使用 ILIKEprepared statements 这会保护我免受 sql injection 的伤害吗?
“根据活动区域设置,可以使用关键字 ILIKE 代替 LIKE 使匹配不区分大小写。这不在 SQL 标准中,而是 PostgreSQL 扩展。”在 9.3 中像魅力一样工作
ILIKE 比 lower(column_name) like %expression% 慢。
@PatrykImosa:您能否详细说明或展示 ILIKE 变慢的示例?
J
James Brown

您还可以使用 POSIX 正则表达式,例如

SELECT id FROM groups where name ~* 'administrator'

SELECT 'asd' ~* 'AsD' 返回 t


我遇到了同样的问题,我需要在我的 PostgreSQL 数据库上进行不区分大小写的搜索。我考虑将用户输入字符串转换为正则表达式。现在,使用 ~* 而不是 = 或 LIKE 效果很好!我不需要创建新的索引、列或其他任何东西。当然,正则表达式搜索比直接字节比较慢,但我认为对性能的影响不会比处理两组数据(一个小写或大写仅用于搜索,然后必须检索相应的原始数据)大得多另一组的数据)。此外,这更清洁!
很好,但是例如如何使用 regexp_matches() 呢?
根据 postgres docs:运算符 ~~ 相当于 LIKE,而 ~~* 对应于 ILIKE。还有 !~~ 和 !~~* 运算符分别代表 NOT LIKE 和 NOT ILIKE。所有这些运算符都是 PostgreSQL 特定的。
当文本中包含括号时,我遇到了一个问题,它不起作用。比如:“代码(LC)”
遇到特殊字符的问题。
E
EstevaoLuis

通过 INSTR 的功能,使用 ~* 可以大大提高性能。

SELECT id FROM groups WHERE name ~* 'adm'

返回名称包含 OR 等于 'adm' 的行。


嘿,罗宾,欢迎来到 SO。詹姆斯布朗的回答已经提出了这个解决方案。此外,您提出的答案不会以任何方式利用正则表达式。
~* 不是完全不区分大小写的匹配。它是正则表达式模式匹配。在您的示例中,如果 db 包含 ADM,则 where name ~* 'Adm'where name ~* 'Ad' 将产生结果。请改用 ILIKE
s
samzna

ILIKE 在这种情况下工作:

SELECT id 
  FROM groups
 WHERE name ILIKE 'Administrator'

M
MUGABA

使用ILIKE

select id from groups where name ILIKE 'adminstration';

如果您来 expressjs 背景和名称是一个变量,请使用

select id from groups where name ILIKE $1;

J
James Hudnall

对于不区分大小写的参数化查询,您可以使用以下语法:

 "select * from article where upper(content) LIKE upper('%' || $1 || '%')"

D
DEV Tiago França
-- Install 'Case Ignore Test Extension'
create extension citext;

-- Make a request
select 'Thomas'::citext in ('thomas', 'tiago');

select name from users where name::citext in ('thomas', 'tiago');

A
Anand Tripathi
select id from groups where name in ('administrator', 'ADMINISTRATOR', 'Administrator')

请在您的答案中添加一些解释,以便其他人可以从中学习