pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
citext模块提供一种大小写不敏感的字符串类型 citext。本质上,它在比较值时会在内部调用 lower。除此之外,它的行为几乎与 text完全相同。
在PostgreSQL中进行大小写不敏感匹配的标准方法, 一直是在比较值时使用lower函数,例如:
SELECT * FROM tab WHERE lower(col) = LOWER(?);
这种做法效果尚可,但有几个缺点:
它会让 SQL 语句变得冗长,而且你必须时刻记得同时对列和查询值调用 lower。
除非你创建一个使用lower的函数索引,否则它不会使用索引。
如果把列声明为UNIQUE或PRIMARY KEY,隐式生成的索引仍然是大小写敏感的。因此,它既无法用于大小写不敏感搜索,也不能以大小写不敏感的方式强制唯一性。
citext 数据类型让你可以免去在 SQL 查询中调用 lower,并且允许主键不区分大小写。与 text 一样,citext 也与区域设置相关,这意味着 大写字符和小写字符如何比较取决于 LC_CTYPE 区域设置 的规则。同样,这种行为与在查询中使用 lower 完全 一致。但由于这是由数据类型透明地完成的,因此你不必在查询中 额外记住任何特殊处理。
下面是一个简单的使用示例:
CREATE TABLE users (
nick CITEXT PRIMARY KEY,
pass TEXT NOT NULL
);
INSERT INTO users VALUES ( 'larry', md5(random()::text) );
INSERT INTO users VALUES ( 'Tom', md5(random()::text) );
INSERT INTO users VALUES ( 'Damian', md5(random()::text) );
INSERT INTO users VALUES ( 'NEAL', md5(random()::text) );
INSERT INTO users VALUES ( 'Bjørn', md5(random()::text) );
SELECT * FROM users WHERE nick = 'Larry';
这个SELECT语句仍会返回一个元组,尽管nick列中存的是larry,而查询条件写的是Larry。
为了尽可能贴近大小写不敏感排序规则的行为,许多比较操作符和函数 都提供了 citext 专用版本。例如,当应用于 citext 时,正则表达式操作符 ~ 和 ~* 表现相同:它们都会以大小写不敏感的方式比较。 !~ 和 !~* 也是如此, LIKE 操作符 ~~ 和 ~~*、 以及 !~~ 和 !~~* 也一样。如果你 希望进行大小写敏感匹配,可以先转换为 text 再比较。
同样地,如果这些函数的参数是citext,它们也会以大小写不敏感方式进行匹配:
regexp_replace()
regexp_split_to_array()
regexp_split_to_table()
replace()
split_part()
strpos()
translate()
对于正则表达式函数,如果你想按大小写敏感方式匹配,可以指定 “c”标志来强制大小写敏感匹配。否则,若要获得大小写敏感行为, 就必须在调用这些函数之前先把值转换为text。
citext 的大小写折叠行为依赖于数据库的 LC_CTYPE 设置,因此它如何比较值是在运行 initdb 创建群集时确定的。按照 Unicode 标准中的 定义,它并不是真正意义上的大小写不敏感。实际上,这意味着只要 你对当前排序规则满意,通常也会对 citext 的比较结果 满意。但是,如果数据库中存有多种语言的数据,而排序规则只适用 于其中某一种语言,那么其他语言的用户可能会发现查询结果并不 符合预期。
citext不如text高效,因为操作符函数和 B-树比较函数必须复制数据,并将数据转换为小写后才能进行比较。不过,在需要大小写不敏感匹配时,它仍然比使用lower略高效一些。
如果你在某些场景下需要大小写敏感比较,而在另一些场景下又需要 大小写不敏感比较,那么 citext 并不会帮上太多忙。标准 做法是使用 text 类型,并在需要大小写不敏感比较时手工 调用 lower;如果这类比较只是偶尔出现,这种做法是 完全可行的。如果你大多数时候都需要大小写不敏感行为,而只是在 少数场景下需要大小写敏感比较,那么可以考虑把数据存储为 citext,并在需要大小写敏感比较时显式地把列转换为 text。无论哪种情况,如果你希望这两类搜索都足够快, 就都需要建立两个索引。
包含 citext 操作符的模式必须位于当前 search_path 中(通常是 public); 如果不在,执行的将是普通的、大小写敏感的 text 比较。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。