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()
對於 regexp 函數,如果您想要區分大小寫地比對,您可以指定 「c」 旗標來強制執行區分大小寫的比對。 否則,如果您想要區分大小寫的行為,則必須在使用這些函數之一之前轉換為 text
。
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
以正確處理。
如果您在文件中看到任何不正確、與您使用特定功能的體驗不符或需要進一步說明的地方,請使用此表格回報文件問題。