Подтвердить что ты не робот

Добавление ключа в пустой столбец hstore

В соответствии с документацией postgres вы добавляете ключ в столбец hstore следующим образом:

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

Но, похоже, это работает только в том случае, если поле hstore не пустое. Например:

postgres=# create table htest (t text, h hstore);
CREATE TABLE
postgres=# insert into htest (t) VALUES ('key');
INSERT 0 1
postgres=# update htest set h = h || ('foo'=>'bar') where t='key';
UPDATE 1
postgres=# select * from htest;
  t  | h 
-----+---
 key | 
(1 row)

Обновление прошло успешно, но hstore не обновлялся. Однако:

postgres=# update htest set h = ('foo'=>'bar') where t='key';
UPDATE 1
postgres=# select * from htest;
  t  |      h       
-----+--------------
 key | "foo"=>"bar"
(1 row)

postgres=# update htest set h = h || ('bar'=>'foo') where t='key';
UPDATE 1
postgres=# select * from htest;
  t  |             h              
-----+----------------------------
 key | "bar"=>"foo", "foo"=>"bar"
(1 row)

Есть ли способ атомно добавить ключ в hstore без предварительной проверки, нет ли hstore?

4b9b3361

Ответ 1

Я думаю, что проблема здесь в том, что у hstore у вас есть null, и null ИЛИ какой-то hstore имеет значение null.

Лучшее решение, которое, вероятно, не лучшее решение, состоит в том, чтобы сделать таблицу с пустой пустой hstore по умолчанию, а не разрешать null. Затем ваши примеры работают так, как вам хотелось бы:

postgres=# create table htest (t text, h hstore default hstore(array[]::varchar[]));
CREATE TABLE
postgres=# insert into htest (t) values ('key');
INSERT 0 1
postgres=# update htest set h = h || ('foo'=>'bar') where t='key';
UPDATE 1
postgres=# select * from htest;
  t  |      h       
-----+--------------
 key | "foo"=>"bar"
(1 row)

Я, к сожалению, не вижу более чистого способа создания пустой hstore, чем hstore(array[]::varchar[]), но это не значит, что лучшего способа нет. Вы можете включить это в свое обновление hstore раньше, чем так:

update htest set h = coalesce(h, hstore(array[]::varchar[])) || ('foo'=>'bar') where t='key';

Таким образом, вам не нужно воссоздавать таблицу. Я считаю, что это довольно грубо. Надеюсь, это поможет.

Ответ 2

Чтобы этого избежать, вам необходимо убедиться, что hstore создан как пустой, а не пустой. Вы можете добавить пустой hstore в существующую таблицу:

ALTER TABLE htest ADD h HSTORE NOT NULL DEFAULT '';

Или вы можете изменить существующий hstore на пустой:

ALTER TABLE htest ALTER COLUMN h SET NOT NULL;
ALTER TABLE htest ALTER COLUMN h SET DEFAULT '';

Обратите внимание, что при установке столбца в "NOT NULL" значение "Выход" не может быть пустым.

Ответ 3

как насчет:

UPDATE htest SET h = COALESCE(h, '') || ('foo'=>'bar') WHERE t='key';

Ответ 4

Для версии Postgres 9.1:

UPDATE htest SET h = COALESCE(h, hstore('')) || hstore('foo', 'bar') WHERE t='key';