【问题标题】:iterate over json array elements in postgresql遍历postgresql中的json数组元素
【发布时间】: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 变量的情况下执行此操作。

【问题讨论】:

    标签: sql json postgresql plpgsql


    【解决方案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 这样的声明。
    猜你喜欢
    • 2012-12-03
    • 2021-08-12
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    • 2021-01-14
    • 1970-01-01
    • 2015-01-16
    • 1970-01-01
    相关资源
    最近更新 更多