citextモジュールは、大文字小文字の区別がない文字列型を提供します。
これは値の比較の際、基本的に内部的でlower
を呼び出します。
この他はほぼtextと同様に動作します。
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', md5(random()::text) ); INSERT INTO users VALUES ( 'Tom', md5(random()::text) ); INSERT INTO users VALUES ( 'Damian', md5(random()::text) ); INSERT INTO users VALUES ( 'NEAL', md5(random()::text) ); INSERT INTO users VALUES ( 'Bjørn', md5(random()::text) ); SELECT * FROM users WHERE nick = 'Larry';
SELECT文は、nick列が"larry"に設定され、問い合わせが"Larry"に対してであっても、1つのタプルを返します。
大文字小文字の区別のない照合をできる限り正確にエミュレートするために、citext独自版の各種比較演算子と関数があります。 例えば正規表現演算子~および~*は、citextに適用する時に同じ動作を提供します。 これら両方は大文字小文字を区別することなく比較します。 !~や!~*だけではなくLIKE演算子、~~、~~*、!~~、!~~*でも同じことが言えます。 もし大文字小文字を区別して比較したい場合は、いつでも比較前にtextにキャストすることができます。
引数がcitextであれば、同様にして以下の関数は大文字小文字を区別しない一致を実行します。
regexp_replace()
regexp_split_to_array()
regexp_split_to_table()
replace()
split_part()
strpos()
translate()
正規表現関数(RegExp関数)では、大文字小文字を区別して一致させたい場合"c"フラグを付けて、強制的に大文字小文字を区別して一致させることができます。 そうしないと、大文字小文字を区別させたい場合にはこれらの関数のいずれかを使用する前段階でtextにキャストしなければなりません。
citextの動作は使用するデータベースのLC_CTYPEに依存します。 どのように値を比較するかは、クラスタ作成のためにinitdbを実行したときに決定されます。 Unicode標準の定義という観点では、本当に大文字小文字の区別がないものではありません。 実質的に何を意味しているかというと、使用している照合が十分なものであれば、citextによる比較も十分なものになるはずです。 しかしデータベースに様々な言語でデータを格納している場合は、ある言語のユーザは照合が他の言語用のものであった場合想定外の問い合わせ結果を得るかもしれません。
演算子関数およびB-Tree比較関数でデータの複製を作成しそれを比較のために小文字に変換しなければなりませんので、citextはtextほど効率的ではありません。
しかし大文字小文字の区別をしない一致をさせるためにlower
を使用する場合よりかなり効率的です。
citextは、ある文脈では大文字小文字の区別を行い、またある文脈では大文字小文字の区別を行わない比較をする必要がある場合、あまり役に立ちません。
標準的な解法はtext型を使用し、大文字小文字を区別する比較が必要であれば手作業でlower
関数を使用することです。
これは大文字小文字を区別しない比較の必要性がまれであれば、問題なく動作します。
大文字小文字を区別しない比較がほとんどで、大文字小文字を区別する比較の必要性がまれである場合は、データをcitextとして格納し、大文字小文字を区別する比較の際にその列を明示的にtextにキャストすることを検討してください。
どちらの場合でも、2種類の検索の両方を高速にするために2つのインデックスを作成しなければならないでしょう。