2025年9月25日: PostgreSQL 18 釋出!
支援版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4

F.9. citext — 預設不區分大小寫的字串型別 #

citext 模組提供了一種預設不區分大小寫的字元型別 citext。本質上,它在比較值時內部呼叫 lower。除此之外,它的行為與 text 型別幾乎完全相同。

提示

考慮使用“非確定性排序規則”(請參閱 第 23.2.2.4 節)來替代此模組。它們可用於不區分大小寫、不區分重音符號以及其他組合的比較,並且能更正確地處理更多 Unicode 特殊情況。

此模組被認為是受信任的,這意味著非超級使用者也可以在其擁有的資料庫上安裝它,前提是他們具有 CREATE 許可權。

F.9.1. 基本原理 #

PostgreSQL 中執行不區分大小寫匹配的標準方法是在比較值時使用 lower 函式,例如:

SELECT * FROM tab WHERE lower(col) = LOWER(?);

這工作得相當好,但存在一些缺點:

  • 它使您的 SQL 語句冗長,並且您必須始終記住在列和查詢值上都使用 lower

  • 除非您使用 lower 建立了一個函式索引,否則它不會使用索引。

  • 如果您將列宣告為 UNIQUEPRIMARY KEY,則隱式生成的索引是區分大小寫的。因此,它對於不區分大小寫的搜尋無濟於事,並且不會強制不區分大小寫的唯一性。

citext 資料型別允許您在 SQL 查詢中省略 lower 的呼叫,並允許主鍵不區分大小寫。citexttext 一樣具有區域設定感知性,這意味著大寫和小寫字元的匹配取決於資料庫的 LC_CTYPE 設定的規則。同樣,此行為與在查詢中使用 lower 相同。但由於資料型別透明地處理了這個問題,因此您不必在查詢中記住做任何特殊處理。

F.9.2. 使用方法 #

這是一個簡單的使用示例:

CREATE TABLE users (
    nick CITEXT PRIMARY KEY,
    pass TEXT   NOT NULL
);

INSERT INTO users VALUES ( 'larry',  sha256(random()::text::bytea) );
INSERT INTO users VALUES ( 'Tom',    sha256(random()::text::bytea) );
INSERT INTO users VALUES ( 'Damian', sha256(random()::text::bytea) );
INSERT INTO users VALUES ( 'NEAL',   sha256(random()::text::bytea) );
INSERT INTO users VALUES ( 'Bjørn',  sha256(random()::text::bytea) );

SELECT * FROM users WHERE nick = 'Larry';

SELECT 語句將返回一個元組,儘管 nick 列設定為 larry 並且查詢是針對 Larry 的。

F.9.3. 字串比較行為 #

citext 透過將每個字串轉換為小寫(如同呼叫 lower 一樣)然後正常比較結果來執行比較。因此,例如,如果 lower 對兩個字串產生相同的結果,則這兩個字串被視為相等。

為了儘可能精確地模擬不區分大小寫的排序規則,存在一些 citext 特定的字串處理運算子和函式版本。例如,當應用於 citext 時,正則表示式運算子 ~~* 表現出相同的行為:它們都進行不區分大小寫的匹配。對於 !~!~* 也是如此,同樣適用於 LIKE 運算子 ~~~~*,以及 !~~!~~*。如果您想進行區分大小寫的匹配,可以將運算子的引數轉換為 text

同樣,如果其引數為 citext,則以下所有函式都執行不區分大小寫的匹配:

  • regexp_match()

  • regexp_matches()

  • regexp_replace()

  • regexp_split_to_array()

  • regexp_split_to_table()

  • replace()

  • split_part()

  • strpos()

  • translate()

對於正則表示式函式,如果您想進行區分大小寫的匹配,可以指定“c”標誌來強制進行區分大小寫的匹配。否則,如果您想要區分大小寫的行為,則必須在使用這些函式之前將資料轉換為 text

F.9.4. 限制 #

  • citext 的大小寫轉換行為取決於資料庫的 LC_CTYPE 設定。因此,它的值比較方式在資料庫建立時就已確定。它並不是嚴格按照 Unicode 標準定義的“大小寫不敏感”。實際上,這意味著,只要您對您的排序規則滿意,您就會對 citext 的比較滿意。但如果您資料庫中儲存了不同語言的資料,一種語言的使用者可能會發現他們的查詢結果不符合預期,因為排序規則是為另一種語言設定的。

  • PostgreSQL 9.1 開始,您可以為 citext 列或資料值附加 COLLATE 規範。目前,citext 運算子在比較大小寫轉換後的字串時會遵循非預設的 COLLATE 規範,但最初的大小寫轉換始終根據資料庫的 LC_CTYPE 設定(即,如同給出了 COLLATE "default")進行。這可能在未來的版本中進行更改,以便兩個步驟都遵循輸入的 COLLATE 規範。

  • citext 的效率不如 text,因為運算子函式和 B-tree 比較函式必須複製資料並將其轉換為小寫進行比較。此外,只有 text 支援 B-Tree 重複資料刪除。但是,citext 比使用 lower 進行不區分大小寫的匹配效率稍高。

  • 如果您需要在某些上下文中區分大小寫,而在其他上下文中不區分大小寫地比較資料,那麼 citext 幫助不大。標準答案是使用 text 型別,並在需要不區分大小寫比較時手動呼叫 lower 函式;如果僅偶爾需要不區分大小寫比較,這效果還不錯。如果您大部分時間需要不區分大小寫行為,而偶爾需要區分大小寫,請考慮將資料儲存為 citext,並在需要區分大小寫比較時顯式將該列轉換為 text。在這兩種情況下,如果您希望兩種搜尋都快速,您都需要兩個索引。

  • 包含 citext 運算子的模式必須位於當前 search_path 中(通常是 public);如果不在,則會呼叫正常的區分大小寫的 text 運算子。

  • 為了比較而將字串轉換為小寫的方法不能正確處理某些 Unicode 特殊情況,例如當一個大寫字母有兩個小寫字母對應的情況。Unicode 因此區分“大小寫對映”和“大小寫摺疊”。請使用非確定性排序規則而不是 citext 來正確處理這種情況。

F.9.5. 作者 #

David E. Wheeler <>

受 Donald Fraser 的原始 citext 模組啟發。

提交更正

如果您在文件中發現任何不正確的內容、與您在使用特定功能時的體驗不符或需要進一步澄清之處,請使用此表格報告文件問題。