作为Postgres和SQL的新手,我在Postgres 9.6中有以下场景:
table1
"Myjson" JSON
"DateOfAcquisition" DATE
"Id" INT
在"Myjson"
中,有一个列表,我通过FOR
循环进行迭代。
我的目标是将每个json列表的元素放在table1
中的另一个表中:
table2
jsonelem1 INT
jsonelem2 INT
"DateOfAcquisition" DATE
"Id" INT
我编写了以下用于解析json字段的代码,但我不确定如何为第一个表的每个记录运行for
循环。
DO
$BODY$
DECLARE
omgjson json := myjsonfield; -- this should change for every row of the first table
i json;
myJsonelem1 INT;
myJsonelem2 INT;
begin
FOR i IN SELECT * FROM json_array_elements(omgjson)
loop
myJsonelem2 i->> 'jsonsubfield'::INT;
INSERT INTO destinationTable VALUES (myJsonelem2,DateOfAcquisition);
END LOOP;
END;
$BODY$ language plpgsql
答案 0 :(得分:1)
与循环相比,基于集合的方法通常 更快(并且更短,更不容易出错)。
以设置of your answer 为基础,这与您提出的问题大不相同。
INSERT INTO table2(myfield, data) -- cleaner: explicit target columns
SELECT k."myField", j.i ->> 'data'
FROM table1 k, json_array_elements(k."ScrapedJson" -> 'calendar_days') j(i)
WHERE NOT k."HasBeenProcessed"
-- ORDER BY ??? -- you might want to order rows favorably?
隐含的 LATERAL
加入是此处的关键技术。
... FROM table1 k, json_array_elements(...) ...
简称:
... FROM table1 k
CROSS JOIN LATERAL json_array_elements(...) ...
显然,"ScrapedJson" -> 'calendar_days'
是一个JSON数组,而不是你在问题中写的“列表”。
相关:
请自己帮忙,避免在Postgres中使用双引号的CaMeL案例名称。在您的问题和答案中混合使用带引号和未加引号的标识符只会让人感到困惑。我在你的问题中引用了列名,以便在某种程度上符合你的答案。我的常设建议:专门使用合法的,小写的,不带引号的名称。
对于大多数工作负载,请考虑数据类型jsonb
而不是json
。
答案 1 :(得分:0)
感谢Lawrence,这里是任何感兴趣的人的解决方案。
我想知道,有更好的方法吗?
DO
$BODY$
DECLARE
i json;
k RECORD;
mydata INT;
begin
FOR k IN SELECT * from TABLE1 where "HasBeenProcessed" = FALSE
LOOP
FOR i IN SELECT * FROM json_array_elements(k."ScrapedJson" -> 'calendar_days')
LOOP
mydata = i->> 'data';
INSERT INTO "Table2" VALUES (k."myField",mydata);
END LOOP;
end LOOP;
END;
$BODY$ language plpgsql