向一个空的hstore列添加键值对

19
根据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中?
4个回答

17

我认为这里的问题是你有一个空的hstore,而null或某些hstore也为空。

我最好的解决方案,可能不是最好的解决方案,是创建一个默认为空的hstore表,而不是允许为空。然后你的例子就可以按照你想要的方式工作:

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

这样你就不需要重新创建表格。虽然我认为这种方法相当不好,但希望能对你有所帮助。


谢谢!我意识到我的hstore是空的,但我不知道这与一个空的hstore有什么不同。 - janr
3
对未来某些人会有所帮助的提示。我使用的是8.4版本,创建空的 hstore 类型时使用的是 hstore('') 而不是 hstore(array[]::varchar[])。 - trex005

7
为了避免这种情况,您需要确保hstore被创建为空而不是为null。您可以向现有表中添加一个空的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”时,现有值不能为null。

6
如何呢?
UPDATE htest SET h = COALESCE(h, '') || ('foo'=>'bar') WHERE t='key';

5
对于Postgres版本> 9.1
UPDATE htest SET h = COALESCE(h, hstore('')) || hstore('foo', 'bar') WHERE t='key';

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接