2012-02-16 23 views
17

Zgodnie z dokumentacją postgres, po dodaniu klucza do kolumny hstore następująco:Dodawanie klucza do pustej kolumnie hstore

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

Ale wydaje działają tylko wtedy, gdy pole hstore nie jest pusta. Na przykład:

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) 

Aktualizacja przebiegła pomyślnie, ale hstore nie został zaktualizowany. Jednakże:

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) 

Czy istnieje sposób atomowo dodać klucz do hstore bez uprzedniego sprawdzenia, czy hstore jest pusty?

Odpowiedz

16

Myślę, że problem polega na tym, że hstore, który masz, ma wartość NULL, i null LUB jakiś hstore jest pusty.

Najlepszym rozwiązaniem, jakie mam, prawdopodobnie nie jest najlepszym rozwiązaniem, jest ustawienie domyślnego pustego hstore zamiast dopuszczenia wartości null. Wtedy twoje przykłady działają jak chcesz:

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) 

ja niestety nie widzę czystszy sposób, aby utworzyć pustą hstore niż hstore(array[]::varchar[]) ale to nie znaczy, że nie ma lepszego sposobu. Możesz dodać to do swojej aktualizacji hstore, tak jak poprzednio:

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

W ten sposób nie trzeba ponownie tworzyć tabeli. Uważam, że dość brutto. Mam nadzieję że to pomoże.

+0

Dzięki! Zdałem sobie sprawę, że mój hstore był nieważny, ale nie wiedziałem, że to coś innego niż pusty hstore. – janr

+0

Dobre rzeczy, dzięki Daniel! –

+2

Może być pomocne dla kogoś w przyszłości. Używam 8.4 i tworzę pusty hstore z hstore ('') zamiast hstore (array [] :: varchar []) – trex005

6

Aby tego uniknąć, należy się upewnić, że plik hstore jest pusty i niezerowy. Możesz dodać pustą hstore do istniejącej tabeli:

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

Albo można zmienić istniejący hstore opróżnić:

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

Należy pamiętać, że wartości wychodzące nie może być null, gdy ustawić kolumnę " NIE JEST ZEREM'.

6

jak about:

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

Dla PostgreSQL wersji > 9,1:

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