将键添加到空hstore列

时间:2012-02-16 19:42:31

标签: postgresql

根据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 个答案:

答案 0 :(得分:17)

我认为这里的问题是你拥有的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,但这并不意味着没有更好的方法。你可以像以前一样将它合并到你之前的hstore更新中:

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

这样您就不需要重新创建表格了。我觉得相当严重。希望这会有所帮助。

答案 1 :(得分: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。

答案 2 :(得分:6)

怎么样:

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

答案 3 :(得分:4)

对于Postgres版本> 9.1

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