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 || hstorehstoreを連結します。'a=>b, c=>d'::hstore || 'c=>x, d=>q'::hstore"a"=>"b", "c"=>"x", "d"=>"q"
hstore ? texthstoreがキーを含むかどうか。'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 #= hstorerecord内のフィールドをhstoreの対応する値で置換します。後述の例を参照 
%% hstoreキーと値を変更してhstoreを配列に変換します。%% 'a=>foo, b=>bar'::hstore{a,foo,b,bar}
%# hstorehstoreをキーと値の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)hstorehstore型の単一項目を作成します。hstore('a', 'b')"a"=>"b"
akeys(hstore)text[]hstoreのキーを配列として入手します。akeys('a=>1,b=>2'){a,b}
skeys(hstore)setof texthstoreのキーを集合として入手します。skeys('a=>1,b=>2')
a
b
avals(hstore)text[]hstoreの値を配列として入手します。avals('a=>1,b=>2'){1,2}
svals(hstore)setof texthstoreの値を集合として入手します。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[])hstorehstoreの部分集合を取り出します。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)booleanhstoreがキーを含むかどうか。exist('a=>1','a')t
defined(hstore,text)booleanhstoreがキーに対して非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)recordrecord内のフィールドを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 BYORDER BYDISTINCTの式で使用することができます。 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');

recordhstoreに変換します。

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 , Moscow, Moscow University, Russia

Teodor Sigaev , Moscow, Delta-Soft Ltd., Russia

追加の改良はAndrew Gierth ,United Kingdomによりなされました。