如何将 JSON 数组(或 JSON 数组)传递给 pg 函数以插入到表中?

Posted

技术标签:

【中文标题】如何将 JSON 数组(或 JSON 数组)传递给 pg 函数以插入到表中?【英文标题】:How to pass an array of JSON (or JSON array) to pg function to be INSERTed into a Table? 【发布时间】:2021-11-30 14:31:53 【问题描述】:

将json数组的行插入表中的功能:

create table mytable(col1 text, col2 boolean, col3 boolean);
create function fun1(vja json[])
... as $$
begin
  foreach v in array json_array_elements(vja)
  loop
    insert into mytable(col1, col2, col3)
    values(v->'col1', v->'col2'::boolean, v->'col3'::boolean);
  end loop;
end;
$$;

调用这个函数:

select fun1('[
    "col1": "turow1@af.com", "col2": false, "col3": true, 
    "col1": "xy2@af.com", "col2": false, "col3": true 
    ]')

或这种形式:

select fun1('[
    "col1": "turow1@af.com", "col2": "false", "col3": "true", 
    "col1": "xy2@af.com", "col2": "false", "col3": "true", 
    ]')

或这种形式:

select fun1('[
    "col1": "turow1@af.com", "col2": "false", "col3": "true", 
    "col1": "xy2@af.com", "col2": "false", "col3": "true", 
    ]'::json[])

总是收到:

ERROR:  malformed array literal: "[
  "col1": "turow1@af.com", "col2": "false", "col3": "true", 
  "col1": "xy2@af.com", "col2": "false", "col3": "true", 
  ]"
LINE 2:  '[
         ^
DETAIL:  "[" must introduce explicitly-specified array dimensions.
SQL state: 22P02
Character: 136

【问题讨论】:

【参考方案1】:

JSON 数组 (json) 不同于 JSON 值的 Postgres 数组 (json[])。

SELECT '["foo": "bar", "foo1": "bar1"]'::json;  -- JSON array

对比:

SELECT '"\"foo\": \"bar\"","\"foo1\": \"bar1\""'::json[]  -- array of JSON

第一个是嵌套在单个 JSON 值中的数组,第二个是 JSON 值的数组。

JSON 的 Postgres 数组 (json[])

您的(固定!)功能:

CREATE OR REPLACE FUNCTION fun1(vja json[])
  RETURNS void
  LANGUAGE plpgsql AS
$func$
DECLARE
   v json;
BEGIN
   FOREACH v IN ARRAY vja
   LOOP
      INSERT INTO mytable(col1, col2, col3)
      VALUES(v ->> 'col1', (v ->> 'col2')::bool, (v ->> 'col3')::bool);
   END LOOP;
END
$func$;

期待这样的调用(注意 json[] 文字的所有转义):

SELECT fun1('"\"col1\": \"turow1@af.com\", \"col2\": false, \"col3\": true","\"col1\": \"xy2@af.com\", \"col2\": false, \"col3\": true"'::json[]);

见:

How to pass custom type array to Postgres function

但是过程中单个INSERTjson_populate_record()胜过在函数中循环:

CREATE OR REPLACE PROCEDURE proc1(vja json[])
  LANGUAGE sql AS
$proc$
INSERT INTO mytable  -- target column list redundant in this particular case
SELECT r.*
FROM   unnest(vja) v, json_populate_record(NULL::mytable, v) r
$proc$;

见:

When to use stored procedure / user-defined function?

或者使用 Postgres 14 或更高版本中的标准 SQL 变体更简单:

CREATE OR REPLACE PROCEDURE proc1(vja json[])
BEGIN ATOMIC
INSERT INTO mytable
SELECT r.*
FROM   unnest(vja) v, json_populate_record(NULL::mytable, v) r;
END;

见:

What does BEGIN ATOMIC ... END mean in a PostgreSQL SQL function / procedure?

调用(!):

CALL proc1('"\"col1\": \"turow1@af.com\", \"col2\": false, \"col3\": true","\"col1\": \"xy2@af.com\", \"col2\": false, \"col3\": true"'::json[]);

db小提琴here

JSON 数组 (json)

通常,您希望像尝试过的那样传递 JSON 数组。 所以,现在用json_populate_recordset()

CREATE OR REPLACE PROCEDURE proc2(vja json)
  LANGUAGE sql AS
$proc$
INSERT INTO mytable
SELECT * FROM json_populate_recordset(NULL::mytable, vja);
$proc$;

或者(Postgres 14):

CREATE OR REPLACE PROCEDURE proc2(vja json)
BEGIN ATOMIC
INSERT INTO mytable
SELECT * FROM json_populate_recordset(NULL::mytable, vja);
END;

调用(现在您可以使用最初测试的值!):

CALL proc2('[
    "col1": "turow1@af.com", "col2": false, "col3": true, 
    "col1": "xy2@af.com", "col2": false, "col3": true 
    ]');

db小提琴here

【讨论】:

很棒的细节和推荐!! Q1 关于 JSON 数组(json)pg 的 JSON 数组(json[]),如果节点 API 传入的参数值为[col1: 'a1@a.com', col2: false, col3: true, col1: 'a2@a.com', col2: false, col3: true],选择哪种形式? Q2 固定功能在public 中有效,但在其他operator does not exist: text ->> unknown 中有效,缺少什么?非常感谢! 第 12 页 Q1:这是一个 JSON 数组 (json)。 Q2:错误信息表明类型text,这里应该是类型json

以上是关于如何将 JSON 数组(或 JSON 数组)传递给 pg 函数以插入到表中?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Json 数组作为统一字段传递给 WWWform

如何从ajax将多个json数组传递给控制器​​?

如何将对象类型的 json 数组传递给 MVC 控制器类

如何使用 GET 请求将 JSON 数组传递给 Controller 方法?

将JSON数组从javascript传递给spring mvc控制器

iOS Swift 如何从 UIWebView 将 JSON 字符串和数组或字典传递给 Javascript?