为每条记录解析一个带有FOR循环的JSON列?

时间:2018-05-27 11:40:45

标签: json postgresql for-loop plpgsql set-returning-functions

作为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

2 个答案:

答案 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