如何将 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但是在过程中单个INSERT
和json_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 函数以插入到表中?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 GET 请求将 JSON 数组传递给 Controller 方法?