2016-02-29 90 views
1

當嘗試一個JSONB_ARRAY_ELEMENTS調用的結果分配給一個VARCHAR array(以備後用在SELECT ... WHERE IN (UNNEST(...))語句),下面的存儲功能:分配JSONB_ARRAY_ELEMENTS結果爲VARCHAR陣列

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結果到一個數組嗎?

UPDATE:

我跟了尼克的提醒(謝謝),但現在卡在接下來的步驟:

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

您近距離...

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

爲了,你需要寫一個自包含SELECT語句中使用的expression IN (subquery)結構:

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' 
); 
+0

其實我也用'sids',但是謝謝。 'ANY'不會比'UNNEST'慢嗎? –

+1

如果「sid」列被索引,並且相對有選擇性,那麼「ANY」通常會更快。 'UNNEST'版本在查詢計劃方面具有更多的靈活性,並且在索引不起作用的情況下往往會處於頂峯。如果有疑問,只需比較兩個查詢之間的'EXPLAIN ANALYSE'輸出。 –