将JSONB_ARRAY_ELEMENTS结果分配给VARCHAR数组

时间:2016-02-29 11:42:03

标签: arrays postgresql postgresql-9.5 postgresql-json

尝试将JSONB_ARRAY_ELEMENTS调用的结果分配给VARCHAR array时(稍后在SELECT ... WHERE IN (UNNEST(...))语句中使用),以下存储的函数:

CREATE OR REPLACE FUNCTION test1(
        IN in_sids jsonb,
        OUT out_uid integer)
        RETURNS integer AS
$func$
DECLARE
        sids varchar[];
        uids integer[];
BEGIN
        sids := (SELECT x->>'sid' FROM JSONB_ARRAY_ELEMENTS(in_sids) x);
        -- uids := (SELECT uid FROM social WHERE sid IN (UNNEST(sids)));

        RAISE NOTICE 'sids = %', sids;
        RAISE NOTICE 'uids = %', uids;

        SELECT 1;
END
$func$ LANGUAGE plpgsql;

不幸打印错误:

# select test1('[{"sid":"aaa"},{"sid":"bbb"}]'::jsonb);

ERROR:  more than one row returned by a subquery used as an expression
CONTEXT:  SQL statement "SELECT (SELECT x->>'sid' FROM JSONB_ARRAY_ELEMENTS(in_sids) x)"
PL/pgSQL function test1(jsonb) line 6 at assignment

所以我尝试使用ARRAY_AGG -

来修复作业
sids := SELECT ARRAY_AGG(SELECT x->>'sid' FROM JSONB_ARRAY_ELEMENTS(in_sids) x);

但得到语法错误:

ERROR:  syntax error at or near "SELECT"
LINE 10:         sids := SELECT ARRAY_AGG(SELECT x->>'sid' FROM JSONB...
                         ^

如何将JSONB_ARRAY_ELEMENTS结果存储到数组中?

更新

我跟随尼克的建议(谢谢),但现在停留在下一步:

CREATE OR REPLACE FUNCTION test1(
        IN in_sids jsonb,
        OUT out_uid integer)
        RETURNS integer AS
$func$
DECLARE
        sids varchar[];
        uids integer[];
BEGIN
        sids := (SELECT ARRAY_AGG(x->>'sid') FROM JSONB_ARRAY_ELEMENTS(in_sids) x);
        uids := (SELECT uid FROM social WHERE sid IN (UNNEST(sids)));

        SELECT 1;
END
$func$ LANGUAGE plpgsql;

尝试在SELECT ... WHERE IN ...语句中使用数组时:

# select test1('[{"sid":"aaa"},{"sid":"bbb"}]'::jsonb);
ERROR:  argument of IN must not return a set
LINE 1: SELECT (SELECT uid FROM social WHERE sid IN (UNNEST(si...
                                              ^
QUERY:  SELECT (SELECT uid FROM social WHERE sid IN (UNNEST(sids)))
CONTEXT:  PL/pgSQL function test1(jsonb) line 7 at assignment

1 个答案:

答案 0 :(得分:1)

你很亲密......

sids := (SELECT ARRAY_AGG(x->>'sid') FROM JSONB_ARRAY_ELEMENTS(in_sids) x);

为了使用expression IN (subquery)构造,您需要编写一个自包含的SELECT语句:

uids := (SELECT ARRAY_AGG(uid) FROM social WHERE sid IN (SELECT UNNEST(sids)));

或者,您可以使用ANY检查值是否在数组中:

uids := (SELECT ARRAY_AGG(uid) FROM social WHERE sid = ANY(sids));

如果您未在以后的某个计算中使用sids数组,则可以将这些数组合并为一个查询:

uids := (
  SELECT array_agg(uid)
  FROM social
  JOIN JSONB_ARRAY_ELEMENTS(in_sids) x ON
    sid = x->>'sid'
);