citext

PostgreSQL 8.4.1文書
前のページ | 巻戻し | 付録 F. 追加で提供されるモジュール | 早送り | 次のページ

# F.6. citext

`citext`モジュールは、大文字小文字の区別がない文字列型を提供します。 これは値の比較の際、基本的に内部的で`lower`を呼び出します。 この他はほぼ`text`と同様に動作します。

## F.6.1. 論拠

PostgreSQLにおいて大文字小文字の区別のない比較を行う標準的な手法は、値を比べる際に以下のように`lower`関数を使用することでした。例です。

       SELECT * FROM tab WHERE lower(col) = LOWER(?);

これは合理的によく動作しますが、いくつか欠点があります。

- 作成するSQL文を冗長にします。 また常に列と問い合わせる値の両方に`lower`を使用することを忘れないようにしなければなりません。

- `lower`を使用する関数インデックスを作成していない限り、インデックスを使用しません。

- `UNIQUE`または`PRIMARY KEY`として列を宣言するのであれば、暗黙的生成されるインデックスは大文字小文字を区別します。このため、大文字小文字を区別しない検索では使えず、また、大文字小文字を区別しない一意性を強制させられません。

`citext`データ型によりSQL問い合わせ内の`lower`呼び出しを省くことができます。 さらに、大文字小文字の区別がないプライマリキーを実現できます。 `citext`は`text`と同様にロケールも考慮します。 つまり大文字と小文字の比較は、`LC_CTYPE`ロケール設定の規則に依存します。 繰り返しますが、この動作は`lower`を使用した問い合わせと同一です。 しかしこのデータ型によって透過的に行われますので、問い合わせで特殊なことを行うことを覚えておく必要はありません。

## F.6.2. 使用法

簡単な例を示します。

       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"に対してであっても、１つのタプルを返します。

## F.6.3. 文字列比較の動作

大文字小文字の区別のない照合をできる限り正確にエミュレートするために、`citext`独自版の各種比較演算子と関数があります。 例えば正規表現演算子`~`および`~*`は、`citext`に適用する時に同じ動作を提供します。 これら両方は大文字小文字を区別することなく比較します。 `!~`や`!~*`だけではなく`LIKE`演算子、`~~`、`~~*`、`!~~`、`!~~*`でも同じことが言えます。 もし大文字小文字を区別して比較したい場合は、いつでも比較前に`text`にキャストすることができます。

引数が`citext`であれば、同様にして以下の関数は大文字小文字を区別しない一致を実行します。

- `regexp_replace()`

- `regexp_split_to_array()`

- `regexp_split_to_table()`

- `replace()`

- `split_part()`

- `strpos()`

- `translate()`

正規表現関数（RegExp関数）では、大文字小文字を区別して一致させたい場合"c"フラグを付けて、強制的に大文字小文字を区別して一致させることができます。 そうしないと、大文字小文字を区別させたい場合にはこれらの関数のいずれかを使用する前段階で`text`にキャストしなければなりません。

## F.6.4. 制限

- `citext`の動作は使用するデータベースの`LC_CTYPE`に依存します。 どのように値を比較するかは、クラスタ作成のためにinitdbを実行したときに決定されます。 Unicode標準の定義という観点では、本当に大文字小文字の区別がないものではありません。 実質的に何を意味しているかというと、使用している照合が十分なものであれば、`citext`による比較も十分なものになるはずです。 しかしデータベースに様々な言語でデータを格納している場合は、ある言語のユーザは照合が他の言語用のものであった場合想定外の問い合わせ結果を得るかもしれません。

- 演算子関数およびB-Tree比較関数でデータの複製を作成しそれを比較のために小文字に変換しなければなりませんので、`citext`は`text`ほど効率的ではありません。 しかし大文字小文字の区別をしない一致をさせるために`lower`を使用する場合よりかなり効率的です。

- `citext`は、ある文脈では大文字小文字の区別を行い、またある文脈では大文字小文字の区別を行わない比較をする必要がある場合、あまり役に立ちません。 標準的な解法は`text`型を使用し、大文字小文字を区別する比較が必要であれば手作業で`lower`関数を使用することです。 これは大文字小文字を区別しない比較の必要性がまれであれば、問題なく動作します。 大文字小文字を区別しない比較がほとんどで、大文字小文字を区別する比較の必要性がまれである場合は、データを`citext`として格納し、大文字小文字を区別する比較の際にその列を明示的に`text`にキャストすることを検討してください。 どちらの場合でも、2種類の検索の両方を高速にするために２つのインデックスを作成しなければならないでしょう。

## F.6.5. Author

David E. Wheeler `<david@kineticode.com>`

Donald Fraserによる`citext`モジュール原本でからの触発

前のページ | ホーム | 次のページ
chkpass | 上に戻る | cube