根据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?
答案 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';