遍历postgresql中的json数组元素

Posted

技术标签:

【中文标题】遍历postgresql中的json数组元素【英文标题】:iterate over json array elements in postgresql 【发布时间】:2018-05-16 09:59:50 【问题描述】:

我有一个像这样的 json


    "elements": [ "element1", "element2", "element3" ]

我想遍历它的元素并打印它们。 我是这样做的

do $$
declare
    datajson jsonb := '
        "elements": [ "element1", "element2", "element3", "element4" ]
    ';
    element varchar(128);
begin
    foreach element in array jsonb_array_elements(datajson->'elements')
    loop
        raise notice '%', element;
    end loop;
end;
$$;

但它失败并出现错误query select jsonb_array_elements(datajson->'elements') returned more than one row

有什么问题?

更新

试过这个建议:

do $$
declare
    datajson jsonb := '
        "elements": [ "element1", "element2", "element3", "element4" ]
    ';
    element varchar(128);
begin
    foreach element in array
        SELECT array_agg(jsonb_array_elements) FROM jsonb_array_elements(datajson->'elements')
    loop
        raise notice '%', element;
    end loop;
end;
$$;

但这只会给出语法错误:

ERROR:  42601: syntax error at or near "SELECT"
LINE 7:     SELECT array_agg(jsonb_array_elements) FROM jsonb_array_...
            ^
LOCATION:  scanner_yyerror, scan.l:1134

尝试在不使用 FOR r IN (...) 并声明 RECORD 变量的情况下执行此操作。

【问题讨论】:

【参考方案1】:

只是:

so=# with c(j) as (values('
    "elements": [ "element1", "element2", "element3" ]
'::jsonb))
select jsonb_array_elements(j->'elements') from c;
 jsonb_array_elements
----------------------
 "element1"
 "element2"
 "element3"
(3 rows)

但如果你想提高它:

so=# do $$
declare
    datajson jsonb := '
        "elements": [ "element1", "element2", "element3", "element4" ]
    ';
    element varchar(128);
    r record;
begin
    for r in (select jsonb_array_elements(datajson->'elements') element)
    loop
        raise notice '%', r.element;
    end loop;
end;
$$;
NOTICE:  "element1"
NOTICE:  "element2"
NOTICE:  "element3"
NOTICE:  "element4"
DO

我假设您将 json 数组与 postgres 数组混淆了——它们不一样。还有jsonb_array_elementsreturns setof,不是数组

【讨论】:

如果每个条目在 "name" : "value", "fields": ["a1", "a2"] 这样的字段中都有自己的子数组怎么办? 写一个我想说的递归 CTE 谢谢 - 我知道如何使用 FOR r IN (...),但我希望避免声明 RECORD 变量。【参考方案2】:

jsonb_array_elements() 将数组的元素作为表返回,而不是作为数组。

使用

FOR element IN
    SELECT jsonb_array_elements FROM jsonb_array_elements(datajson->'elements')
LOOP
     ...
END LOOP;

遍历表格行,而不是数组。

或者使用array_agg()将表格转为数组:

FOREACH element IN ARRAY
    (SELECT array_agg(jsonb_array_elements) FROM jsonb_array_elements(datajson->'elements'))
LOOP
     ...
END LOOP;

但它可能工作较慢(表将像以前的情况一样创建,然后将被转换)

【讨论】:

所以基本上它返回一个单列的表?我可以把它转换成数组吗? 是的。编辑了答案。 第二个示例不起作用:获取ERROR: 42601: syntax error at or near "SELECT" - 使用版本 11。还尝试将子查询放在括号中,但结果相同。 @user9645 请检查您是否忘记了LOOP ... END LOOP;。请注意,我没有 Postgres 11 来测试答案。 我没有忘记循环/结束循环 - 我只是将你的 FOREACH element in ARRAY SELECT... 语句粘贴到我的测试用例中并得到 ERROR: 42601: syntax error at or near "SELECT" LINE 7: SELECT array_agg(jsonb_array_elements) FROM jsonb_array_... LOCATION: scanner_yyerror, scan.l:1134 我建议你验证你可以使用 @ 987654331@ 反对 SELECT 这样的声明。

以上是关于遍历postgresql中的json数组元素的主要内容,如果未能解决你的问题,请参考以下文章

以随机顺序从 JSON 数组中获取元素

将包含对象数组的 json 传递给 PostgreSQL 函数会引发格式错误的数组文字。意外的数组元素

查询 JSON 列中的数组元素

Zapier - Catch Hook - JSON 数组 - 遍历数组中的每个项目

js遍历对象的几种方法以及 删除对象中的某个元素的方法

js数组怎么调换两个元素的位置