PostgreSQL:从json向表中插入数据

时间:2013-07-28 06:08:19

标签: json postgresql insert

现在我使用手动将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插入表中是否有更优雅的vay?

2 个答案:

答案 0 :(得分:13)

json_populate_record没有简单的方法可以返回一个标记,表示“生成此值”。

PostgreSQL not 允许您插入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 }对于未定义的列。这可能不是您对所有列的意图,并且当DEFAULT json_populate_record中使用时,会导致INSERT如何处理json_populate_record的问题表达

所以我猜{{1}}可能没有您希望生成密钥的行那么有用。

答案 1 :(得分:10)

继续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"}');