2012-02-16 28 views
17

Theo tài liệu Postgres, bạn thêm một chìa khóa để một cột hstore như sau:Thêm một chìa khóa để một cột hstore trống

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

Nhưng nó dường như chỉ có tác dụng nếu lĩnh vực hstore là không có sản phẩm nào. Ví dụ:

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) 

Cập nhật thành công, nhưng hstore chưa được cập nhật. Tuy nhiên:

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) 

Có cách nào để thêm nguyên tử khóa vào hstore mà trước tiên không kiểm tra xem hstore có trống không?

Trả lời

16

Tôi nghĩ rằng vấn đề ở đây là hstore bạn có là null, và null HOẶC một số hstore là null.

Giải pháp tốt nhất mà tôi có, có lẽ không phải là giải pháp tốt nhất, là làm cho bảng có kho lưu trữ trống mặc định hơn là cho phép null. Sau đó, ví dụ của bạn làm việc như bạn muốn:

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) 

tôi tiếc là không nhìn thấy một cách sạch hơn để tạo ra một hstore trống hơn hstore(array[]::varchar[]) nhưng điều đó không có nghĩa là không có một cách tốt hơn. Bạn có thể kết hợp điều này vào bản cập nhật hstore của mình từ trước như sau:

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

Bằng cách này bạn không cần phải tạo lại bảng. Tôi thấy rằng khá thô mặc dù. Hi vọng điêu nay co ich.

+0

Cảm ơn! Tôi nhận ra rằng hstore của tôi là vô giá trị, nhưng tôi đã không nhận ra rằng đó là bất kỳ khác nhau từ một hstore trống. – janr

+0

Công cụ tốt, cảm ơn Daniel! –

+2

Có thể là một lưu ý hữu ích cho một người nào đó trong tương lai. Tôi đang sử dụng 8.4 và tôi tạo hstore rỗng với hstore ('') thay vì hstore (array [] :: varchar []) – trex005

6

Để tránh điều này, bạn cần đảm bảo hstore được tạo dưới dạng trống và không rỗng. Bạn có thể thêm một hstore trống để một bảng hiện có:

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

Hoặc bạn có thể thay đổi hstore hiện tại của bạn để trống:

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

Xin lưu ý rằng giá trị xuất cảnh không thể được null khi bạn thiết lập cột ' CÓ GIÁ TRỊ'.

6

thế nào về:

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

Đối với Postgres phiên bản > 9.1:

UPDATE htest SET h = COALESCE(h, hstore('')) || hstore('foo', 'bar') WHERE t='key'; 
Các vấn đề liên quan