Перейти к основному содержимому

hstore — тип данных «ключ-значение» (hstore)

примечание

Эта страница переведена при помощи нейросети GigaChat.

Этот модуль реализует тип данных hstore, предназначенный для хранения наборов пар ключ/значение внутри одного значения PostgreSQL. Это может быть полезно в различных сценариях, таких как строки с множеством атрибутов, которые редко проверяются, или полуструктурированные данные. Ключи и значения являются простыми текстовыми строками.

Модуль считается «надежным», то есть его могут устанавливать обычные пользователи, обладающие привилегией CREATE на текущей базе данных.

Внешнее представление 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) символы обратной косой черты должны быть правильно экранированы.

При выводе двойные кавычки всегда окружают ключи и значения, даже когда это не обязательно.

Операторы и функции hstore

Операторы, предоставляемые модулем, показаны в таблице «Операторы hstore», функции в таблице «Функции hstore».

Операторы 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Заменяет поля в левом операнде (который должен быть составным типом) соответствующими значениями из hstoreROW(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}}

Функции 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 ( text[], text[] ) → hstoreКонструирует hstore из отдельных массивов ключей и значенийhstore(ARRAY['a','b'], ARRAY['1','2'])"a"=>"1", "b"=>"2"
hstore ( text, text ) → hstoreСоздает элементарный hstorehstore('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_jsonb ( hstore ) → jsonbПреобразует значение hstore в значение jsonb, преобразуя все ненулевые значения в строки JSONЭта функция используется неявно при приведении значения hstore к типу jsonb
hstore_to_json_loose ( hstore ) → jsonПреобразует hstore в значение json, но пытается различить числовые и логические значения, чтобы они не были заключены в кавычки в формате JSONhstore_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, но пытается различить числовые и логические значения, чтобы они не были заключены в кавычки в формате JSONhstore_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Заменяет поля в левом операнде (который должен быть составным типом) с совпадающими значениями из hstorepopulate_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, если подстрочный индекс является NULL или этот ключ не существует в hstore. Таким образом, обращение по индексу не сильно отличается от оператора ->. Обновление с подстрочным индексом завершается неудачно, если подстрочный индекс равен NULL, в противном случае он заменяет значение для этого ключа, добавляя запись в hstore, если ключ еще не существует.

Индексы

hstore поддерживает индексы GiST и GIN для операторов @>, ?, ?& и ?|. Например:

CREATE INDEX hidx ON testhstore USING GIST (h);

CREATE INDEX hidx ON testhstore USING GIN (h);

Класс операторов GiST gist_hstore_ops аппроксимирует набор пар ключ/значение как сигнатуру битовой карты. Его необязательный целочисленный параметр siglen определяет длину подписи в байтах. Длина по умолчанию составляет 16 байт. Допустимые значения длины подписи находятся между 1 и 2024 байтами. Более длинные подписи приводят к более точному поиску (сканированию меньшей доли индекса и меньшего количества страниц кучи) за счет увеличения размера индекса.

Пример создания такого индекса с длиной подписи 32 байта:

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

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);

Примеры

Добавление ключа или обновление существующего ключа новым значением:

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)

Статистика

Тип 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
...................

Совместимость

Начиная с PostgreSQL 9.0, hstore использует внутреннее представление, отличное от предыдущих версий. Это не представляет препятствия для обновлений дампа/восстановления, поскольку текстовое представление (используемое в дампе) остается неизменным.

В случае двоичного обновления совместимость сохраняется за счет того, что новый код распознает данные старого формата. Это повлечет за собой незначительную потерю производительности при обработке данных, которые еще не были изменены новым кодом. Можно принудительно обновить все значения в столбце таблицы, выполнив оператор UPDATE, как показано ниже:

UPDATE tablename SET hstorecol = hstorecol || '';

Еще один способ сделать это:

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

Метод ALTER TABLE требует блокировки ACCESS EXCLUSIVE для таблицы, но не приводит к раздуванию таблицы старыми версиями строк.

Преобразования

Дополнительные расширения доступны для реализации преобразований типа hstore для языков PL/Perl и PL/Python. Расширения для PL/Perl называются hstore_plperl и hstore_plperlu, для доверенного и недоверенного PL/Perl. Если установить эти преобразования и указать их при создании функции, значения hstore будут отображаться на хеш-карты Perl. Расширение для PL/Python называется hstore_plpython3u. При его использовании, значения hstore будут отображены в словари Python.

Внимание

Рекомендуется устанавливать расширения преобразования в той же схеме, что и hstore. В противном случае возникают угрозы безопасности во время установки, если схема расширения преобразования содержит объекты, определенные враждебным пользователем.