18

现在我使用手动将 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 插入到表中?

4

2 回答 2

18

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

PostgreSQL不允许您插入NULL以指定应生成的值。如果您要求NULLPg 期望意味着 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可以返回DEFAULTNULL不是未定义的列。这可能不是您对所有列的预期,并且会导致在表达式中使用DEFAULT时如何处理的问题。json_populate_recordINSERT

所以我想json_populate_record对于生成键的行可能没有你希望的那么有用。

于 2013-07-28T13:34:31.650 回答
13

继续Craig 的回答,您可能需要编写某种存储过程来执行必要的动态 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"}');
于 2015-02-17T23:11:42.600 回答