hstore

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

# F.16. hstore

本モジュールはキー、値の組み合わせの集合を単一のPostgreSQL値に格納するための`hstore`データ型を実装します。 あまり厳密に検査されない属性を多く持つ行や半構造化データなど、多くの状況で有用になる可能性があります。 キーと値は単純なテキスト文字列です。

## F.16.1. `hstore`の外部表現

入力および出力で使用される`hstore`値のテキスト表現はカンマで区切られた、ゼロ以上の`key` `=>` `value`という組み合わせを含みます。 以下に例を示します。

    k => v
    foo => bar, baz => whatever
    "1-a" => "anything at all"

組み合わせの順序は重要ではありません（出力時に再現されないこともあります）。 組み合わせ間や`=>`記号の前後の空白文字は無視されます。 キーや値が空白文字、カンマ、`=`、`>`を含む場合は二重引用符でくくります。 キーや値に二重引用符やバックスラッシュを含めるには、バックスラッシュでエスケープしてください。

`hstore`内の各キーは一意です。 重複するキーを持つ`hstore`を宣言すると、`hstore`には1つしか保存されません。 またどちらが残るかは保証されません。

    SELECT 'a=>1,a=>2'::hstore;
      hstore
    ----------
     "a"=>"1"

値はSQLの`NULL`を取ることができます（キーは不可）。 以下に例を示します。

    key => NULL

`NULL`キーワードは大文字小文字の区別をしません。 `null`を普通の文字列"NULL"として扱うためには二重引用符でくくってください。

> 注意: 入力として使用される場合`hstore`テキスト書式は、前もって必要な引用符付けやエスケープ処理を適用することに注意してください。 パラメータとして`hstore`リテラルを渡す場合、追加処理は必要ありません。 しかし、引用符付けしたリテラル定数として渡す場合には、単一引用符および(`standard_conforming_strings`設定パラメータに依存しますが)バックスラッシュ文字をすべて正しくエスケープしなければなりません。 文字列定数の取り扱いについては項4.1.2.1を参照してください。

出力の場合、厳密に必要がない場合であっても、常にキーと値は二重引用符でくくられます。

## F.16.2. `hstore`の演算子と関数

`hstore`モジュールで提供される演算子を表F-6に、関数を表F-7に示します。

表 F-6. `hstore`演算子

演算子 | 説明 | 例 | 結果
--- | --- | --- | ---
`hstore` `->` `text` | キーの値を取り出します（存在しなければ`NULL`） | `'a=>x, b=>y'::hstore -> 'a'` | `x`
`hstore` `->` `text[]` | キーの値を取り出します（存在しなければ`NULL`） | `'a=>x, b=>y, c=>z'::hstore -> ARRAY['c','a']` | `{"z","x"}`
`text` `=>` `text` | 単一の`hstore`組み合わせを作成します。 | `'a' => 'b'` | `"a"=>"b"`
`hstore` `||` `hstore` | `hstore`を連結します。 | `'a=>b, c=>d'::hstore || 'c=>x, d=>q'::hstore` | `"a"=>"b", "c"=>"x", "d"=>"q"`
`hstore` `?` `text` | `hstore`がキーを含むかどうか。 | `'a=>1'::hstore ? 'a'` | `t`
`hstore` `?&` `text[]` | `hstore`が指定したキーをすべて含むかどうか。 | `'a=>1,b=>2'::hstore ?& ARRAY['a','b']` | `t`
`hstore` `?|` `text[]` | `hstore`が指定したキーのいずれかを含むかどうか。 | `'a=>1,b=>2'::hstore ?| ARRAY['b','c']` | `t`
`hstore` `@>` `hstore` | 左辺は右辺を含むかどうか。 | `'a=>b, b=>1, c=>NULL'::hstore @> 'b=>1'` | `t`
`hstore` `<@` `hstore` | 左辺は右辺に含まれるかどうか。 | `'a=>c'::hstore <@ 'a=>b, b=>1, c=>NULL'` | `f`
`hstore` `-` `text` | 左辺からキーを削除します。 | `'a=>1, b=>2, c=>3'::hstore - 'b'::text` | `"a"=>"1", "c"=>"3"`
`hstore` `-` `text[]` | 左辺からキー(複数)を削除します。 | `'a=>1, b=>2, c=>3'::hstore - ARRAY['a','b']` | `"c"=>"3"`
`hstore` `-` `hstore` | 左辺から一致する組み合わせを削除します。 | `'a=>1, b=>2, c=>3'::hstore - 'a=>4, b=>2'::hstore` | `"a"=>"1", "c"=>"3"`
`record` `#=` `hstore` | `record`内のフィールドを`hstore`の対応する値で置換します。 | 後述の例を参照 |
`%%` `hstore` | キーと値を変更して`hstore`を配列に変換します。 | `%% 'a=>foo, b=>bar'::hstore` | `{a,foo,b,bar}`
`%#` `hstore` | `hstore`をキーと値の2次元配列に変換します。 | `%# 'a=>foo, b=>bar'::hstore` | `{{a,foo},{b,bar}}`

> 注意: PostgreSQL 8.2より前では、含有演算子`@>`と`<@`はそれぞれ`@`と`~`と呼ばれていました。 これらの名前はまだ利用できますが、廃止予定であり、最終的にはなくなります。 古い名前がコアの幾何データ型が従う規約と反対であることに注意してください。

> 注意: `=>`演算子は廃止予定であり、将来のリリースで削除される可能性があります。 代わりに`hstore(text, text)`関数を使用してください。

表 F-7. `hstore`の関数

関数 | 戻り値の型 | 説明 | 例 | 結果
--- | --- | --- | --- | ---
`hstore(record)` | `hstore` | レコードまたは行から`hstore`を生成します。 | `hstore(ROW(1,2))` | `f1=>1,f2=>2`
`hstore(text[])` | `hstore` | 配列から`hstore`を生成します。配列はキー、値の配列でも2次元の配列でも構いません | `hstore(ARRAY['a','1','b','2']) || hstore(ARRAY[['c','3'],['d','4']])` | `a=>1, b=>2, c=>3, d=>4`
`hstore(text[], text[])` | `hstore` | キー、値で分けた配列から`hstore`を作成します。 | `hstore(ARRAY['a','b'], ARRAY['1','2'])` | `"a"=>"1","b"=>"2"`
`hstore(text, text)` | `hstore` | `hstore`型の単一項目を作成します。 | `hstore('a', 'b')` | `"a"=>"b"`
`akeys(hstore)` | `text[]` | `hstore`のキーを配列として入手します。 | `akeys('a=>1,b=>2')` | `{a,b}`
`skeys(hstore)` | `setof text` | `hstore`のキーを集合として入手します。 | `skeys('a=>1,b=>2')` |
    a
    b
`avals(hstore)` | `text[]` | `hstore`の値を配列として入手します。 | `avals('a=>1,b=>2')` | `{1,2}`
`svals(hstore)` | `setof text` | `hstore`の値を集合として入手します。 | `svals('a=>1,b=>2')` |
    1
    2
`hstore_to_array(hstore)` | `text[]` | `hstore`のキーと値を、キーと値を交互に表した配列として入手します。 | `hstore_to_array('a=>1,b=>2')` | `{a,1,b,2}`
`hstore_to_matrix(hstore)` | `text[]` | `hstore`のキーと値を2次元配列として入手します。 | `hstore_to_matrix('a=>1,b=>2')` | `{{a,1},{b,2}}`
`slice(hstore, text[])` | `hstore` | `hstore`の部分集合を取り出します。 | `slice('a=>1,b=>2,c=>3'::hstore, ARRAY['b','c','x'])` | `"b"=>"2", "c"=>"3"`
`each(hstore)` | `setof(key text, value text)` | `hstore`のキーと値を集合として入手します。 | `select * from each('a=>1,b=>2')` |
     key | value
    -----+-------
     a   | 1
     b   | 2
`exist(hstore,text)` | `boolean` | `hstore`がキーを含むかどうか。 | `exist('a=>1','a')` | `t`
`defined(hstore,text)` | `boolean` | `hstore`がキーに対して非`NULL`の値を持つかどうか | `defined('a=>NULL','a')` | `f`
`delete(hstore,text)` | `hstore` | キーに一致する組み合わせを削除します。 | `delete('a=>1,b=>2','b')` | `"a"=>"1"`
`delete(hstore,text[])` | `hstore` | キー(複数)に対応する組み合わせを削除します。 | `delete('a=>1,b=>2,c=>3',ARRAY['a','b'])` | `"c"=>"3"`
`delete(hstore,hstore)` | `hstore` | 第二引数内の組み合わせと一致する組み合わせを削除します。 | `delete('a=>1,b=>2','a=>4,b=>2'::hstore)` | `"a"=>"1"`
`populate_record(record,hstore)` | `record` | `record`内のフィールドを`hstore`の対応する値で置換します。 | 後述の例を参照 |

> 注意: `populate_record`関数の最初の引数は実際には`record`ではなく`anyelement`と宣言されています。 しかし、実行時にはレコード型以外は拒絶されます。

## F.16.3. インデックス

`hstore`は`@>`、`?`、`?&`および`?|`演算子向けのGiSTおよびGINインデックスをサポートします。 以下に例を示します。

    CREATE INDEX hidx ON testhstore USING GIST (h);

    CREATE INDEX hidx ON testhstore USING GIN (h);

`hstore`はまた、`=`演算子向けに`btree`または`hash`インデックスをサポートします。 これにより`hstore`の列を`UNIQUE`と宣言すること、また、`GROUP BY`、`ORDER BY`、`DISTINCT`の式で使用することができます。 `hstore`値のソート順序付けはあまり有用ではありません。 しかしこれらのインデックスは等価値の検索の際に有用になるかもしれません。 `=`比較用のインデックスを以下のように作成します。

    CREATE INDEX hidx ON testhstore USING BTREE (h);

    CREATE INDEX hidx ON testhstore USING HASH (h);

## F.16.4. 例

キーを追加、または、既存のキーを新しい値で更新します。

    UPDATE tab SET h = h || ('c' => '3');

キーを削除します。

    UPDATE tab SET h = delete(h, 'k1');

`record`を`hstore`に変換します。

    CREATE TABLE test (col1 integer, col2 text, col3 text);
    INSERT INTO test VALUES (123, 'foo', 'bar');

    SELECT hstore(t) FROM test AS t;
                       hstore
    ---------------------------------------------
     "col1"=>"123", "col2"=>"foo", "col3"=>"bar"
    (1 row)

`hstore`を事前に定義された`record`型に変換します。

    CREATE TABLE test (col1 integer, col2 text, col3 text);

    SELECT * FROM populate_record(null::test,
                                  '"col1"=>"456", "col2"=>"zzz"');
     col1 | col2 | col3
    ------+------+------
      456 | zzz  |
    (1 row)

`hstore`の値を使用して既存のレコードを変更します。

    CREATE TABLE test (col1 integer, col2 text, col3 text);
    INSERT INTO test VALUES (123, 'foo', 'bar');

    SELECT (r).* FROM (SELECT t #= '"col3"=>"baz"' AS r FROM test t) s;
     col1 | col2 | col3
    ------+------+------
      123 | foo  | baz
    (1 row)

## F.16.5. 統計情報

内在する自由度のため、`hstore`型は異なるキーを多く含むことができます。 有効なキーを検査することはアプリケーション側の作業です。 以下の例では、キー検査および統計情報の入手に関する複数の技法を示します。

簡単な例を示します。

    SELECT * FROM each('aaa=>bq, b=>NULL, ""=>1');

テーブルを使用する例です。

    SELECT (each(h)).key, (each(h)).value INTO stat FROM testhstore;

オンライン統計値です。

    SELECT key, count(*) FROM
      (SELECT (each(h)).key FROM testhstore) AS stat
      GROUP BY key
      ORDER BY count DESC, key;
        key    | count
    -----------+-------
     line      |   883
     query     |   207
     pos       |   203
     node      |   202
     space     |   197
     status    |   195
     public    |   194
     title     |   190
     org       |   189
    ...................

## F.16.6. 互換性

より古いバージョンから更新する場合、ダンプをリストアする前に常に本モジュールの新しいバージョンをデータベースにロードしてください。 さもないと多くの新しい機能が使用できなくなります。

PostgreSQL 9.0から`hstore`の内部表現はこれまでから変更されました。 (ダンプ内で使用される)テキスト表現には変更がありませんので、ダンプ/リストアによる更新の妨げにはなりません。

バイナリによる更新の際、新しいコードで古い書式のデータを認識させることにより、上位互換が保持されます。 これには、新しいコードによりまだ変更されていないデータを処理する際に、性能の劣化を多少伴います。 以下のように`UPDATE`文を実行することによりテーブル列内のすべての値を強制的に更新することができます。

    UPDATE tablename SET hstorecol = hstorecol || '';

上を行う他の方法を以下に示します。

    ALTER TABLE tablename ALTER hstorecol TYPE hstore USING hstorecol || '';

`ALTER TABLE`による方法はテーブルに対して排他ロックを必要とします。 しかし、古いバージョンの行でテーブルが膨張することはありません。

## F.16.7. 作者

Oleg Bartunov `<oleg@sai.msu.su>`, Moscow, Moscow University, Russia

Teodor Sigaev `<teodor@sigaev.ru>`, Moscow, Delta-Soft Ltd., Russia

追加の改良はAndrew Gierth `<andrew@tao11.riddles.org.uk>`,United Kingdomによりなされました。

前のページ | ホーム | 次のページ
fuzzystrmatch | 上に戻る | intagg