2013-07-28 23 views
11

數據插入到表現在我用手動JSON解析成插入串像這樣PostgreSQL的:從JSON

insert into Table (field1, field2) values (val1, val2) 

,但它不是舒適的方式從JSON插入數據! 我發現功能json_populate_record並試圖使用它:

create table test (id serial, name varchar(50)); 
insert into test select * from json_populate_record(NULL::test, '{"name": "John"}'); 

,但它無法與消息:列「ID」空值違反非空約束 PG知道ID是串行的,但僞裝成一個傻瓜。對於所有具有默認設置的夥伴也是如此。

是否有更優雅的同志插入數據從json到表中?

+1

「我找到了函數'json_populate_record'」。嗯。 *哪裏*?什麼是函數定義?你在運行PostgreSQL 9.3 beta嗎,還是從別的地方安裝的? –

+0

這是9.3測試版的功能 – user2627000

回答

10

json_populate_record沒有簡單的方法來返回一個意味着「生成此值」的標記。

PostgreSQL確實不是允許您插入NULL來指定應該生成一個值。如果您要求NULL Pg期望意味着NULL並且不想再次猜測您。另外,生成一個沒有NOT NULL約束的列是完全可以的,在這種情況下,將NULL插入它是完全正確的。

如果你想擁有的PostgreSQL使用的值表默認情況下有兩種方法可以做到這一點:

  • 省略從INSERT列清單列;或
  • 明確寫入DEFAULT,這是隻有在VALUES表達有效

既然你不能使用VALUES(DEFAULT, ...)這裏,你唯一的選擇是從INSERT列列表中忽略列:

regress=# create table test (id serial primary key, name varchar(50)); 
CREATE TABLE 
regress=# insert into test(name) select name from json_populate_record(NULL::test, '{"name": "John"}'); 
INSERT 0 1 

是的,這意味着您必須列出列。實際上,兩次在SELECT列表中,一次在INSERT列表中。

爲了避免這PostgreSQL的需要有指定DEFAULT,作爲一個記錄的值的一種方式,所以json_populate_record可以爲沒有定義的列返回DEFAULT,而不是NULL的需要。這可能不是你想要的所有列,並且會導致當json_populate_record而不是INSERT表達式中使用時如何處理DEFAULT的問題。

所以我認爲json_populate_record可能沒有你所希望的那樣有用於具有生成密鑰的行。

+0

非常酷。基於json輸入,是否還有'UPDATE'的方法? – jney

+0

@jney我不確定你在問什麼。我建議發佈一個新的適當詳細的問題,並將其鏈接回上面的環境。 –

+0

非常有用的信息('json_populate_record'的文檔有點稀疏)。但是,對於「沒有指定值的地方,使用默認值」的效果,確實似乎是一個很好的選擇。 – beldaz

6

Craig's answer繼續,你可能需要編寫某種存儲過程的執行必要的動態SQL,像如下:

CREATE OR REPLACE FUNCTION jsoninsert(relname text, reljson text) 
    RETURNS record AS 
$BODY$DECLARE 
ret RECORD; 
inputstring text; 
BEGIN 
    SELECT string_agg(quote_ident(key),',') INTO inputstring 
    FROM json_object_keys(reljson::json) AS X (key); 
    EXECUTE 'INSERT INTO '|| quote_ident(relname) 
    || '(' || inputstring || ') SELECT ' || inputstring 
    || ' FROM json_populate_record(NULL::' || quote_ident(relname) || ' , json_in($1)) RETURNING *' 
    INTO ret USING reljson::cstring; 
    RETURN ret; 
END; 
$BODY$ 
LANGUAGE plpgsql VOLATILE; 

,你會再與調用

SELECT jsoninsert('test', '{"name": "John"}');