citext
模組提供了一個不區分大小寫的字串類型,citext
。 本質上,它在比較值時在內部呼叫 lower
。 除此之外,它的行為幾乎與 text
完全相同。
考慮使用非決定性的定序(請參閱第 23.2.2.4 節)而不是此模組。 它們可用於不區分大小寫的比較、不區分重音符號的比較和其他組合,並且它們可以正確處理更多 Unicode 特殊情況。
此模組被視為“受信任的”,也就是說,具有目前資料庫的 CREATE
權限的非超級使用者可以安裝它。
在 PostgreSQL 中執行不區分大小寫比對的標準方法是在比較值時使用 lower
函式,例如
SELECT * FROM tab WHERE lower(col) = LOWER(?);
這在合理程度上有效,但存在一些缺點
它使您的 SQL 陳述式冗長,並且您必須始終記住對欄位和查詢值都使用 lower
。
它不會使用索引,除非您使用 lower
建立函數索引。
如果您將欄位宣告為 UNIQUE
或 PRIMARY KEY
,則隱式產生的索引會區分大小寫。 因此,它對不區分大小寫的搜尋沒有用處,並且不會以不區分大小寫的方式強制唯一性。
citext
資料類型允許您消除 SQL 查詢中對 lower
的呼叫,並允許主鍵不區分大小寫。citext
具有地區設定感知能力,就像 text
一樣,這表示大寫和小寫字元的比對取決於資料庫的 LC_CTYPE
設定規則。 同樣,此行為與在查詢中使用 lower
相同。 但是由於它是由資料類型透明地完成的,因此您不必記住在查詢中執行任何特殊操作。
這是一個簡單的使用範例
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
。
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
。
citext
的大小寫轉換行為取決於資料庫的 LC_CTYPE
設定。 因此,它如何比較值是在建立資料庫時決定的。 就 Unicode 標準定義的術語而言,它並非真正不區分大小寫。 實際上,這表示只要您對定序感到滿意,您就應該對 citext
的比較感到滿意。 但是,如果您的資料庫中儲存了不同語言的資料,則如果定序適用於另一種語言,一種語言的使用者可能會發現他們的查詢結果不如預期。
從 PostgreSQL 9.1 開始,您可以將 COLLATE
規範附加到 citext
欄位或資料值。 目前,citext
運算符在比較大小寫摺疊字串時將採用非預設 COLLATE
規範,但初始摺疊為小寫始終根據資料庫的 LC_CTYPE
設定完成(也就是說,如同給定 COLLATE "default"
一樣)。 這可能會在未來的版本中更改,以便兩個步驟都遵循輸入的 COLLATE
規範。
由於運算子函式和 B-樹比較函式必須複製資料並將其轉換為小寫以進行比較,因此 citext
不如 text
有效率。此外,只有 text
支援 B-樹去重(deduplication)。然而,citext
比使用 lower
進行不區分大小寫的比對稍微有效率一些。
如果您需要在某些情況下區分大小寫比較資料,而在其他情況下不區分大小寫,那麼 citext
的幫助不大。標準的解決方案是使用 text
類型,並在需要進行不區分大小寫的比較時手動使用 lower
函式;如果只需要偶爾進行不區分大小寫的比較,這樣做是可以的。如果您大部分時間需要不區分大小寫的行為,而很少需要區分大小寫的行為,請考慮將資料儲存為 citext
,並在需要區分大小寫的比較時,將該欄位明確轉換為 text
。無論哪種情況,如果您希望兩種搜尋都很快,您都需要兩個索引。
包含 citext
運算子的綱要(schema)必須在目前的 search_path
中(通常是 public
);如果不是,則會改為調用正常的區分大小寫的 text
運算子。
對於某些 Unicode 特殊情況,例如一個大寫字母有兩個小寫字母等價物的情況,將字串轉換為小寫進行比較的方法無法正確處理。因此,Unicode 區分了大小寫映射(case mapping)和大小寫折疊(case folding)。請使用非決定性的排序規則(collation)而不是 citext
來正確處理這種情況。
如果您在文件中看到任何不正確、與您對特定功能的體驗不符或需要進一步澄清的地方,請使用此表單回報文件問題。