支援的版本: 目前 (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 的文字表示法(用於輸入和輸出)包括零或多個以逗號分隔的 => 配對。 一些範例

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

配對的順序並不重要(並且可能不會在輸出中重現)。 配對之間或 => 符號周圍的空白會被忽略。 將包含空白、逗號、=> 的鍵和值加上雙引號。 若要在鍵或值中包含雙引號或反斜線,請使用反斜線跳脫字元。

hstore 中的每個鍵都是唯一的。 如果宣告具有重複鍵的 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 中的值修改現有的 record

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 字典。

注意

強烈建議將轉換擴充功能安裝在與 hstore 相同的結構描述中。否則,如果轉換擴充功能的結構描述包含敵意使用者定義的物件,則會存在安裝時的安全風險。

F.17.8. 作者 #

Oleg Bartunov , Moscow, Moscow University, Russia

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

Andrew Gierth 的其他增強功能 , United Kingdom

提交更正

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