支援的版本:目前 (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 的呼叫,並允許主鍵不區分大小寫。 citext 具有地區設定意識,就像 text 一樣,這表示大寫和小寫字元的比對取決於資料庫 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()

對於 regexp 函數,如果您想要區分大小寫地比對,您可以指定 c 旗標來強制執行區分大小寫的比對。 否則,如果您想要區分大小寫的行為,則必須在使用這些函數之一之前轉換為 text

F.9.4. 限制 #

  • citext 的大小寫折疊行為取決於資料庫的 LC_CTYPE 設定。因此,它比較值的方式是在建立資料庫時決定的。在 Unicode 標準定義的術語中,它並非真正的大小寫不敏感。實際上,這意味著,只要您對排序規則感到滿意,您就應該對 citext 的比較感到滿意。但是,如果您的資料庫中儲存了不同語言的資料,如果排序規則是針對另一種語言,則一種語言的使用者可能會發現他們的查詢結果與預期不符。

  • PostgreSQL 9.1 開始,您可以將 COLLATE 規範附加到 citext 欄位或資料值。目前,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 模組。

提交更正

如果您在文件中看到任何不正確、與您使用特定功能的體驗不符或需要進一步說明的地方,請使用此表格回報文件問題。