Добавление ключа в пустой столбец hstore - PullRequest
18 голосов
/ 16 февраля 2012

Согласно документации 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)

Обновление прошло успешно, но магазин не был обновлен.Однако:

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 пустым?

Ответы [ 4 ]

17 голосов
/ 17 февраля 2012

Я думаю, что проблема здесь в том, что у вас есть 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(array[]::varchar[]), но это не значит, что лучшего способа нет.Вы можете включить это в свое обновление hstore, как показано ниже:

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

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

7 голосов
/ 21 декабря 2013

Чтобы избежать этого, вам нужно убедиться, что 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».

6 голосов
/ 23 декабря 2014

как насчет:

UPDATE htest SET h = COALESCE(h, '') || ('foo'=>'bar') WHERE t='key';
4 голосов
/ 28 августа 2015

Для Postgres версии > 9,1 :

UPDATE htest SET h = COALESCE(h, hstore('')) || hstore('foo', 'bar') WHERE t='key';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...