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 開始,您可以為 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
來正確處理這種情況。
如果您在文件中發現任何不正確的內容、與您在使用特定功能時的體驗不符或需要進一步澄清之處,請使用此表格報告文件問題。