# F.16.商店

F.16.1.商店外部表征F.16.2.商店运算符和函数F.16.3.索引F.16.4.例子F.16.5.统计数字F.16.6.兼容性F.16.7.转变F.16.8.作者

本模块实现了商店用于在单个PostgreSQL值中存储键/值对集的数据类型。这在各种场景中都很有用,例如具有许多很少检查的属性的行,或者半结构化数据。键和值只是文本字符串。

该模块被认为是“受信任的”,也就是说,它可以由拥有创造当前数据库的权限。

# F.16.1.商店外部表征

一个文本的文本表示商店,用于输入和输出,包括零个或多个*钥匙* => *价值*以逗号分隔的对。例如:

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

成对的顺序不重要(输出时可能不会重现)。两对之间或周围的空格=>符号被忽略。双引号键和值,包括空格、逗号、,=还是>s、 要在键或值中包含双引号或反斜杠,请使用反斜杠将其转义。

每把钥匙商店这是独一无二的。如果你申报商店对于重复的密钥,只有一个将存储在商店对于将保留的内容,也没有任何保证:

SELECT 'a=>1,a=>2'::hstore;
  hstore
### Note

 Keep in mind that the `hstore` text format, when used for input, applies *before* any required quoting or escaping. If you are passing an `hstore` literal via a parameter, then no additional processing is needed. But if you're passing it as a quoted literal constant, then any single-quote characters and (depending on the setting of the `standard_conforming_strings` configuration parameter) backslash characters need to be escaped correctly. See [Section 4.1.2.1](sql-syntax-lexical.html#SQL-SYNTAX-STRINGS) for more on the handling of string constants.

 On output, double quotes always surround keys and values, even when it's not strictly necessary.

### F.16.2. `hstore` Operators and Functions

 The operators provided by the `hstore` module are shown in [Table F.7](hstore.html#HSTORE-OP-TABLE), the functions in [Table F.8](hstore.html#HSTORE-FUNC-TABLE).

**Table F.7. `hstore` Operators**

|                                                                              Operator<br/><br/> Description<br/><br/> Example(s)                                                                              |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|                            `hstore` `->` `text` → `text`<br/><br/> Returns value associated with given key, or `NULL` if not present.<br/><br/>`'a=>x, b=>y'::hstore -> 'a'` → `x`                            |
|            `hstore` `->` `text[]` → `text[]`<br/><br/> Returns values associated with given keys, or `NULL` if not present.<br/><br/>`'a=>x, b=>y, c=>z'::hstore -> ARRAY['c','a']` → `{"z","x"}`             |
|                       `hstore` `||` `hstore` → `hstore`<br/><br/> Concatenates two `hstore`s.<br/><br/>`'a=>b, c=>d'::hstore || 'c=>x, d=>q'::hstore` → `"a"=>"b", "c"=>"x", "d"=>"q"`                        |
|                                                  `hstore` `?` `text` → `boolean`<br/><br/> Does `hstore` contain key?<br/><br/>`'a=>1'::hstore ? 'a'` → `t`                                                   |
|                               `hstore` `?&` `text[]` → `boolean`<br/><br/> Does `hstore` contain all the specified keys?<br/><br/>`'a=>1,b=>2'::hstore ?& ARRAY['a','b']` → `t`                               |
|                             `hstore` `?|` `text[]` → `boolean`<br/><br/> Does `hstore` contain any of the specified keys?<br/><br/>`'a=>1,b=>2'::hstore ?| ARRAY['b','c']` → `t`                              |
|                                    `hstore` `@>` `hstore` → `boolean`<br/><br/> Does left operand contain right?<br/><br/>`'a=>b, b=>1, c=>NULL'::hstore @> 'b=>1'` → `t`                                     |
|                                   `hstore` `<@` `hstore` → `boolean`<br/><br/> Is left operand contained in right?<br/><br/>`'a=>c'::hstore <@ 'a=>b, b=>1, c=>NULL'` → `f`                                   |
|                               `hstore` `-` `text` → `hstore`<br/><br/> Deletes key from left operand.<br/><br/>`'a=>1, b=>2, c=>3'::hstore - 'b'::text` → `"a"=>"1", "c"=>"3"`                                |
|                                `hstore` `-` `text[]` → `hstore`<br/><br/> Deletes keys from left operand.<br/><br/>`'a=>1, b=>2, c=>3'::hstore - ARRAY['a','b']` → `"c"=>"3"`                                 |
|     `hstore` `-` `hstore` → `hstore`<br/><br/> Deletes pairs from left operand that match pairs in the right operand.<br/><br/>`'a=>1, b=>2, c=>3'::hstore - 'a=>4, b=>2'::hstore` → `"a"=>"1", "c"=>"3"`     |
|`anyelement` `#=` `hstore` → `anyelement`<br/><br/> Replaces fields in the left operand (which must be a composite type) with matching values from `hstore`.<br/><br/>`ROW(1,3) #= 'f1=>11'::hstore` → `(11,3)`|
|                           `%%` `hstore` → `text[]`<br/><br/> Converts `hstore` to an array of alternating keys and values.<br/><br/>`%% 'a=>foo, b=>bar'::hstore` → `{a,foo,b,bar}`                           |
|                            `%#` `hstore` → `text[]`<br/><br/> Converts `hstore` to a two-dimensional key/value array.<br/><br/>`%# 'a=>foo, b=>bar'::hstore` → `{{a,foo},{b,bar}}`                            |

**Table F.8. `hstore` Functions**

|                                                                                                                                                                                              Function<br/><br/> Description<br/><br/> Example(s)                                                                                                                                                                                             |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|                                                                                                                                              []() `hstore` ( `record` ) → `hstore`<br/><br/> Constructs an `hstore` from a record or row.<br/><br/>`hstore(ROW(1,2))` → `"f1"=>"1", "f2"=>"2"`                                                                                                                                               |
|                                                                          `hstore` ( `text[]` ) → `hstore`<br/><br/> Constructs an `hstore` from an array, which may be either a key/value array, or a two-dimensional array.<br/><br/>`hstore(ARRAY['a','1','b','2'])` → `"a"=>"1", "b"=>"2"`<br/><br/>`hstore(ARRAY[['c','3'],['d','4']])` → `"c"=>"3", "d"=>"4"`                                                                           |
|                                                                                                                           `hstore` ( `text[]`, `text[]` ) → `hstore`<br/><br/> Constructs an `hstore` from separate key and value arrays.<br/><br/>`hstore(ARRAY['a','b'], ARRAY['1','2'])` → `"a"=>"1", "b"=>"2"`                                                                                                                           |
|                                                                                                                                                           `hstore` ( `text`, `text` ) → `hstore`<br/><br/> Makes a single-item `hstore`.<br/><br/>`hstore('a', 'b')` → `"a"=>"b"`                                                                                                                                                            |
|                                                                                                                                                       []() `akeys` ( `hstore` ) → `text[]`<br/><br/> Extracts an `hstore`'s keys as an array.<br/><br/>`akeys('a=>1,b=>2')` → `{a,b}`                                                                                                                                                        |
|                                                                                                                                      []() `skeys` ( `hstore` ) → `setof text`<br/><br/> Extracts an `hstore`'s keys as a set.<br/><br/>`skeys('a=>1,b=>2')` → ``<br/><br/>```<br/>a<br/>b<br/><br/>```                                                                                                                                       |
|                                                                                                                                                      []() `avals` ( `hstore` ) → `text[]`<br/><br/> Extracts an `hstore`'s values as an array.<br/><br/>`avals('a=>1,b=>2')` → `{1,2}`                                                                                                                                                       |
|                                                                                                                                     []() `svals` ( `hstore` ) → `setof text`<br/><br/> Extracts an `hstore`'s values as a set.<br/><br/>`svals('a=>1,b=>2')` → ``<br/><br/>```<br/>1<br/>2<br/><br/>```                                                                                                                                      |
|                                                                                                                      []() `hstore_to_array` ( `hstore` ) → `text[]`<br/><br/> Extracts an `hstore`'s keys and values as an array of alternating keys and values.<br/><br/>`hstore_to_array('a=>1,b=>2')` → `{a,1,b,2}`                                                                                                                       |
|                                                                                                                           []() `hstore_to_matrix` ( `hstore` ) → `text[]`<br/><br/> Extracts an `hstore`'s keys and values as a two-dimensional array.<br/><br/>`hstore_to_matrix('a=>1,b=>2')` → `{{a,1},{b,2}}`                                                                                                                            |
|  []() `hstore_to_json` ( `hstore` ) → `json`<br/><br/> Converts an `hstore` to a `json` value, converting all non-null values to JSON strings.<br/><br/> This function is used implicitly when an `hstore` value is cast to `json`.<br/><br/>`hstore_to_json('"a key"=>1, b=>t, c=>null, d=>12345, e=>012345, f=>1.234, g=>2.345e+4')` → `{"a key": "1", "b": "t", "c": null, "d": "12345", "e": "012345", "f": "1.234", "g": "2.345e+4"}`   |
|[]() `hstore_to_jsonb` ( `hstore` ) → `jsonb`<br/><br/> Converts an `hstore` to a `jsonb` value, converting all non-null values to JSON strings.<br/><br/> This function is used implicitly when an `hstore` value is cast to `jsonb`.<br/><br/>`hstore_to_jsonb('"a key"=>1, b=>t, c=>null, d=>12345, e=>012345, f=>1.234, g=>2.345e+4')` → `{"a key": "1", "b": "t", "c": null, "d": "12345", "e": "012345", "f": "1.234", "g": "2.345e+4"}`|
|                     []() `hstore_to_json_loose` ( `hstore` ) → `json`<br/><br/> Converts an `hstore` to a `json` value, but attempts to distinguish numerical and Boolean values so they are unquoted in the JSON.<br/><br/>`hstore_to_json_loose('"a key"=>1, b=>t, c=>null, d=>12345, e=>012345, f=>1.234, g=>2.345e+4')` → `{"a key": 1, "b": true, "c": null, "d": 12345, "e": "012345", "f": 1.234, "g": 2.345e+4}`                     |
|                   []() `hstore_to_jsonb_loose` ( `hstore` ) → `jsonb`<br/><br/> Converts an `hstore` to a `jsonb` value, but attempts to distinguish numerical and Boolean values so they are unquoted in the JSON.<br/><br/>`hstore_to_jsonb_loose('"a key"=>1, b=>t, c=>null, d=>12345, e=>012345, f=>1.234, g=>2.345e+4')` → `{"a key": 1, "b": true, "c": null, "d": 12345, "e": "012345", "f": 1.234, "g": 2.345e+4}`                   |
|                                                                                                             []() `slice` ( `hstore`, `text[]` ) → `hstore`<br/><br/> Extracts a subset of an `hstore` containing only the specified keys.<br/><br/>`slice('a=>1,b=>2,c=>3'::hstore, ARRAY['b','c','x'])` → `"b"=>"2", "c"=>"3"`                                                                                                              |
|                                                                         []() `each` ( `hstore` ) → `setof record` ( *`key`* `text`, *`value`* `text` )<br/><br/> Extracts an `hstore`'s keys and values as a set of records.<br/><br/>`select * from each('a=>1,b=>2')` → ``<br/><br/>```<br/> key | value<br/>-----+-------<br/> a   | 1<br/> b   | 2<br/><br/>```                                                                          |
|                                                                                                                                                            []() `exist` ( `hstore`, `text` ) → `boolean`<br/><br/> Does `hstore` contain key?<br/><br/>`exist('a=>1', 'a')` → `t`                                                                                                                                                            |
|                                                                                                                                             []() `defined` ( `hstore`, `text` ) → `boolean`<br/><br/> Does `hstore` contain a non-`NULL` value for key?<br/><br/>`defined('a=>NULL', 'a')` → `f`                                                                                                                                             |
|                                                                                                                                                   []() `delete` ( `hstore`, `text` ) → `hstore`<br/><br/> Deletes pair with matching key.<br/><br/>`delete('a=>1,b=>2', 'b')` → `"a"=>"1"`                                                                                                                                                   |
|                                                                                                                                           `delete` ( `hstore`, `text[]` ) → `hstore`<br/><br/> Deletes pairs with matching keys.<br/><br/>`delete('a=>1,b=>2,c=>3', ARRAY['a','b'])` → `"c"=>"3"`                                                                                                                                            |
|                                                                                                                                  `delete` ( `hstore`, `hstore` ) → `hstore`<br/><br/> Deletes pairs matching those in the second argument.<br/><br/>`delete('a=>1,b=>2', 'a=>4,b=>2'::hstore)` → `"a"=>"1"`                                                                                                                                  |
|                                                                                            []() `populate_record` ( `anyelement`, `hstore` ) → `anyelement`<br/><br/> Replaces fields in the left operand (which must be a composite type) with matching values from `hstore`.<br/><br/>`populate_record(ROW(1,2), 'f1=>42'::hstore)` → `(42,2)`                                                                                             |

 In addition to these operators and functions, values of the `hstore` type can be subscripted, allowing them to act like associative arrays. Only a single subscript of type `text` can be specified; it is interpreted as a key and the corresponding value is fetched or stored. For example,

创建表mytable(h hstore);在mytable中插入值('a=>b,c=>d');选择h[“a”']从mytable;H

# F.16.3.索引

商店有GiST和GIN索引支持@>, ?, ?&?|接线员。例如:

CREATE INDEX hidx ON testhstore USING GIST (h);

CREATE INDEX hidx ON testhstore USING GIN (h);

行动要点GiST opclass将一组键/值对近似为位图签名。它的可选整数参数西格伦以字节为单位确定签名长度。默认长度为16字节。签名长度的有效值在1到2024字节之间。更长的签名会导致更精确的搜索(扫描更少的索引部分和更少的堆页),但代价是索引更大。

创建签名长度为32字节的索引的示例:

CREATE INDEX hidx ON testhstore USING GIST (h gist_hstore_ops(siglen=32));

商店也支持B树搞砸数据库的索引=操作人员这允许商店要声明的列唯一的,或用于分组, 订购人不同的表达。排序商店值不是特别有用,但这些索引可能对等价性查找有用。为创建索引=比较如下:

CREATE INDEX hidx ON testhstore USING BTREE (h);

CREATE INDEX hidx ON testhstore USING HASH (h);

# F.16.4.例子

添加密钥,或使用新值更新现有密钥:

UPDATE tab SET h['c'] = '3';

做同样事情的另一种方法是:

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

如果要在一次操作中添加或更改多个键,则串联方法比订阅更有效:

UPDATE tab SET h = h || hstore(array['q', 'w'], array['11', '12']);

删除密钥:

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

转化为记录商店:

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

SELECT hstore(t) FROM test AS t;
                   hstore                    
### F.16.5. Statistics

 The `hstore` type, because of its intrinsic liberality, could contain a lot of different keys. Checking for valid keys is the task of the application. The following examples demonstrate several techniques for checking keys and obtaining statistics.

 Simple example:

从每个选项中选择*('aaa=>bq,b=>NULL,“=>1');

 Using a table:

创建表stat作为SELECT(每个(h))。键(每个(h))。testhstore的值;

 Online statistics:

选择键,从中计数(*)(选择每个(h))。来自testhstore的密钥)作为统计分组,按密钥顺序按计数描述,密钥;键|计数

# F.16.6.相容性

从PostgreSQL 9.0开始,商店使用与以前版本不同的内部表示形式。这对转储/恢复升级没有障碍,因为文本表示(在转储中使用)没有改变。

在二进制升级的情况下,通过让新代码识别旧格式数据来保持向上兼容性。在处理尚未被新代码修改的数据时,这将带来轻微的性能损失。可以通过执行使现代化声明如下:

UPDATE tablename SET hstorecol = hstorecol || '';

另一种方法是:

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

这个改变桌子方法需要访问独占锁定表,但不会导致旧行版本的表膨胀。

# F.16.7.转变

可以使用其他扩展来实现商店键入PL/Perl和PL/Python语言。PL/Perl的扩展名为hstore_plperl许托鲁,用于受信任和不受信任的PL/Perl。如果安装这些转换并在创建函数时指定它们,商店值被映射到Perl哈希。PL/Python的扩展名为许托鲁蟒蛇, 许托鲁Python2uhstore_Python3u(见第46.1节对于PL/Python命名约定)。如果你使用它们,商店值映射到Python字典。

# 小心

强烈建议将转换扩展安装在与相同的架构中商店。否则,如果转换扩展的架构包含恶意用户定义的对象,则存在安装时安全隐患。

# F.16.8.作者

奥列格·巴图诺夫<[oleg@sai.msu.su](邮寄至:oleg@sai.msu.su)>,莫斯科,莫斯科大学,俄罗斯

特奥多尔·西加耶夫<[teodor@sigaev.ru](邮寄至:teodor@sigaev.ru)>,莫斯科,德尔塔软件有限公司,俄罗斯

Andrew Gierth的其他增强功能<[andrew@tao11.riddles.org.uk](邮寄至:andrew@tao11.riddles.org.uk)>,英国