2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3

F.17. hstore — hstore 鍵/值資料型別 #

本模組實現了 hstore 資料型別,用於在單個 PostgreSQL 值中儲存鍵/值對集合。這在各種場景中都很有用,例如具有許多很少被檢查的屬性的行,或半結構化資料。鍵和值都只是文字字串。

此模組被認為是受信任的,這意味著非超級使用者也可以在其擁有的資料庫上安裝它,前提是他們具有 CREATE 許可權。

F.17.1. hstore 外部表示 #

hstore 的文字表示(用於輸入和輸出)包含零個或多個由逗號分隔的 key => value 對。例如:

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

鍵值對的順序不重要(並且在輸出時可能不會被複制)。鍵值對之間或 => 符號周圍的空白被忽略。包含空格、逗號、=> 的鍵和值需要用雙引號括起來。要在鍵或值中包含雙引號或反斜槓,請用反斜槓對其進行轉義。

hstore 中的每個鍵都是唯一的。如果宣告的 hstore 包含重複的鍵,則只會儲存一個,並且不保證保留哪一個。

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.17.2. hstore 運算子和函式 #

hstore 模組提供的運算子如 表 F.6 所示,函式如 表 F.7 所示。

表 F.6. hstore 運算子

運算子

描述

示例

hstore -> texttext

返回與給定鍵關聯的值,如果不存在則返回 NULL

'a=>x, b=>y'::hstore -> 'a'x

hstore -> text[]text[]

返回與給定鍵關聯的值,如果不存在則返回 NULL

'a=>x, b=>y, c=>z'::hstore -> ARRAY['c','a']{"z","x"}

hstore || hstorehstore

連線兩個 hstore

'a=>b, c=>d'::hstore || 'c=>x, d=>q'::hstore"a"=>"b", "c"=>"x", "d"=>"q"

hstore ? textboolean

hstore 是否包含該鍵?

'a=>1'::hstore ? 'a't

hstore ?& text[]boolean

hstore 是否包含所有指定鍵?

'a=>1,b=>2'::hstore ?& ARRAY['a','b']t

hstore ?| text[]boolean

hstore 是否包含任何指定鍵?

'a=>1,b=>2'::hstore ?| ARRAY['b','c']t

hstore @> hstoreboolean

左運算元是否包含右運算元?

'a=>b, b=>1, c=>NULL'::hstore @> 'b=>1't

hstore <@ hstoreboolean

左運算元是否包含在右運算元中?

'a=>c'::hstore <@ 'a=>b, b=>1, c=>NULL'f

hstore - texthstore

從左運算元中刪除鍵。

'a=>1, b=>2, c=>3'::hstore - 'b'::text"a"=>"1", "c"=>"3"

hstore - text[]hstore

從左運算元中刪除鍵。

'a=>1, b=>2, c=>3'::hstore - ARRAY['a','b']"c"=>"3"

hstore - hstorehstore

從左運算元中刪除與右運算元中匹配的鍵值對。

'a=>1, b=>2, c=>3'::hstore - 'a=>4, b=>2'::hstore"a"=>"1", "c"=>"3"

anyelement #= hstoreanyelement

hstore 中匹配的值替換左運算元(必須是複合型別)中的欄位。

ROW(1,3) #= 'f1=>11'::hstore(11,3)

%% hstoretext[]

hstore 轉換為交替的鍵和值的陣列。

%% 'a=>foo, b=>bar'::hstore{a,foo,b,bar}

%# hstoretext[]

hstore 轉換為二維鍵/值陣列。

%# 'a=>foo, b=>bar'::hstore{{a,foo},{b,bar}}


表 F.7. hstore 函式

函式

描述

示例

hstore ( record ) → hstore

從記錄或行構造 hstore

hstore(ROW(1,2))"f1"=>"1", "f2"=>"2"

hstore ( text[] ) → hstore

從陣列構造 hstore,陣列可以是鍵/值陣列,也可以是二維陣列。

hstore(ARRAY['a','1','b','2'])"a"=>"1", "b"=>"2"

hstore(ARRAY[['c','3'],['d','4']])"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 的鍵和值作為二維陣列提取。

hstore_to_matrix('a=>1,b=>2'){{a,1},{b,2}}

hstore_to_json ( hstore ) → json

hstore 轉換為 json 值,將所有非空值轉換為 JSON 字串。

hstore 值轉換為 json 時,會隱式使用此函式。

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

hstore 轉換為 jsonb 值,將所有非空值轉換為 JSON 字串。

hstore 值轉換為 jsonb 時,會隱式使用此函式。

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

hstore 轉換為 json 值,但嘗試區分數字和布林值,以便它們在 JSON 中不帶引號。

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

hstore 轉換為 jsonb 值,但嘗試區分數字和布林值,以便它們在 JSON 中不帶引號。

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

提取 hstore 的子集,僅包含指定的鍵。

slice('a=>1,b=>2,c=>3'::hstore, ARRAY['b','c','x'])"b"=>"2", "c"=>"3"

each ( hstore ) → setof record ( 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 ( anyelement, hstore ) → anyelement

hstore 中匹配的值替換左運算元(必須是複合型別)中的欄位。

populate_record(ROW(1,2), 'f1=>42'::hstore)(42,2)


除了這些運算子和函式之外,hstore 型別的值還可以透過下標進行訪問,使其行為類似於關聯陣列。只能指定一個 text 型別的下標;它被解釋為鍵,並獲取或儲存相應的值。例如,

CREATE TABLE mytable (h hstore);
INSERT INTO mytable VALUES ('a=>b, c=>d');
SELECT h['a'] FROM mytable;
 h
---
 b
(1 row)

UPDATE mytable SET h['c'] = 'new';
SELECT h FROM mytable;
          h
----------------------
 "a"=>"b", "c"=>"new"
(1 row)

如果下標為 NULL 或者該鍵不存在於 hstore 中,則帶下標的獲取將返回 NULL。(因此,帶下標的獲取與 -> 運算子沒有太大區別。)如果下標為 NULL,則帶下標的更新將失敗;否則,它會替換該鍵的值,如果該鍵尚不存在,則會向 hstore 新增一個條目。

F.17.3. 索引 #

hstore@>, ?, ?&?| 運算子提供 GiST 和 GIN 索引支援。例如

CREATE INDEX hidx ON testhstore USING GIST (h);

CREATE INDEX hidx ON testhstore USING GIN (h);

gist_hstore_ops GiST 運算子類將一組鍵/值對近似為點陣圖簽名。其可選的整數引數 siglen 決定了以位元組為單位的簽名長度。預設長度為 16 位元組。簽名長度的有效值為 1 到 2024 位元組。更長的簽名會導致更精確的搜尋(掃描索引的一小部分和更少的堆頁面),但代價是索引更大。

使用 32 位元組簽名長度建立此類索引的示例

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

hstore 還支援 = 運算子的 btreehash 索引。這允許 hstore 列被宣告為 UNIQUE,或用於 GROUP BYORDER BYDISTINCT 表示式。 hstore 值的排序順序不是特別有用,但這些索引可能對等價查詢有用。為 = 比較建立索引如下

CREATE INDEX hidx ON testhstore USING BTREE (h);

CREATE INDEX hidx ON testhstore USING HASH (h);

F.17.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');

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.17.5. 統計 #

hstore 型別,由於其固有的開放性,可能包含大量不同的鍵。檢查有效鍵是應用程式的任務。以下示例演示了幾種檢查鍵和獲取統計資訊的技術。

簡單示例

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

使用表

CREATE TABLE stat AS SELECT (each(h)).key, (each(h)).value 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.17.6. 相容性 #

從 PostgreSQL 9.0 開始,hstore 使用與以前版本不同的內部表示。由於文字表示(在轉儲中使用)未更改,因此這不會對轉儲/恢復升級造成障礙。

在二進位制升級的情況下,新程式碼透過識別舊格式資料來保持向上相容性。這在處理尚未被新程式碼修改的資料時會帶來輕微的效能損失。可以透過執行如下 UPDATE 語句來強制升級表列中的所有值:

UPDATE tablename SET hstorecol = hstorecol || '';

另一種方法是

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

ALTER TABLE 方法需要表上的 ACCESS EXCLUSIVE 鎖,但不會導致表膨脹舊行版本。

F.17.7. 轉換 #

還提供了其他擴充套件,用於實現 PL/Perl 和 PL/Python 語言的 hstore 型別的轉換。PL/Perl 的副檔名為 hstore_plperlhstore_plperlu,分別用於受信任和不受信任的 PL/Perl。如果安裝這些轉換並在建立函式時指定它們,hstore 值將對映到 Perl 雜湊。PL/Python 的副檔名為 hstore_plpython3u。如果使用它,hstore 值將對映到 Python 字典。

F.17.8. 作者 #

Oleg Bartunov ,莫斯科,莫斯科大學,俄羅斯

Teodor Sigaev ,莫斯科,Delta-Soft 有限公司,俄羅斯

Andrew Gierth ,英國,做出了額外的增強

提交更正

如果您發現文件中的任何內容不正確、與您使用特定功能的經驗不符或需要進一步澄清,請使用 此表單 報告文件問題。