为什么 CITEXT 和 TEXT 之间的比较失败?

ant*_*awn 4 postgresql citext

正如预期的那样,当进行这样的相等测试时,比较成功:

CREATE TABLE citext_test (
    value citext PRIMARY KEY
);

INSERT INTO citext_test VALUES ('one');
INSERT INTO citext_test VALUES ('two');

SELECT * FROM citext_test WHERE value = 'One';
Run Code Online (Sandbox Code Playgroud)

但是,如果要比较的值是“text”类型,则比较失败:

SELECT * FROM citext_test WHERE value = 'One'::text;
Run Code Online (Sandbox Code Playgroud)

使用 EXPLAIN,第一个示例中的原始值似乎被转换为 CITEXT:

Index Only Scan using citext_test_pkey on citext_test  (cost=0.15..8.17 rows=1 width=32)
  Index Cond: (value = 'One'::citext)
Run Code Online (Sandbox Code Playgroud)

我想与连接表中的 TEXT 列进行比较。我真的需要将这些列转换为 CITEXT 才能进行比较吗?我认为使用 CITEXT 的部分优点是不必记住添加这样的东西(例如 LOWER(some_value));

Eva*_*oll 5

我真的需要将这些列转换为 CITEXT 才能进行比较吗?

是的,这就是你必须做的。运营商不是这样工作的。您应该在桌子上设置此类型,这样您就不必这样做。如果一个人说它是不区分大小写的文本,而另一个人说它是区分大小写的文本,则区分大小写的文本获胜。第一个例子之所以有效是因为

SELECT * FROM citext_test WHERE value = 'One';
Run Code Online (Sandbox Code Playgroud)

本质上是一样的

SELECT * FROM citext_test WHERE value = 'One'::unknown;
Run Code Online (Sandbox Code Playgroud)

在内部,运营商将其提升为 citext。你可以和演员们消除歧义,

SELECT * FROM citext_test WHERE value = 'One'::citext;
Run Code Online (Sandbox Code Playgroud)

或函数形式,

SELECT * FROM citext_test WHERE citext_eq(value, 'One');
Run Code Online (Sandbox Code Playgroud)

但适当的解决方案是ALTER TABLE为您要加入的表并将其类型citext也设置为。

  • 你是对的,“区分大小写的文本获胜”就是问题所在。我倾向于认为它不应该,因为 CITEXT 不关心大小写,你可以将它视为匹配 TEXT 所包含的任何内容。也许这只是 CITEXT 作为扩展的副作用,或者也许有人比我投入了更多的思考,并且知道这会导致不良结果的情况。 (2认同)