plpgsql 在循环其元素之前提取数组

plpgsql extract array before loop on it's elements

我正在尝试创建一个以参数为参数的 plpg 函数:

[{'id_product': 100000158, 'd_price': '7,75'}, {'id_product': 100000339, 'd_price': '9,76'}]

或者也许:

{'products': [{'id_product': 100000158, 'd_price': '7,75'}, {'id_product': 100000339, 'd_price': '9,76'}]}

还不能说出最好的方法。

我想将此 jsonb 对象或字符串转换为数组,以便在其上循环。 这个想法是在每个 {'id_product': xxxxxxxxx, 'd_price': 'xxxxx'} 循环 en 所以我如果 table.

中的值相同

执行此操作的最佳方法是什么? 我还在玩jsonb函数。

您可以创建一个包含 JSONB_POPULATE_RECORDSET() 函数的函数

CREATE OR REPLACE FUNCTION fn_extract_elements( i_jsonb JSONB )
RETURNS TABLE (o_product VARCHAR(500), o_price VARCHAR(500))
AS $BODY$
BEGIN
RETURN QUERY

WITH tab AS 
(
 SELECT *
   FROM JSONB_POPULATE_RECORDSET(NULL::record,i_jsonb )
      AS tab(id_product VARCHAR(500), d_price VARCHAR(500))
 )
SELECT *
  FROM tab;

END 
$BODY$
LANGUAGE plpgsql;

并以

这样的方式调用
SELECT *  
  FROM fn_extract_elements(
'[{"id_product": "100000158", "d_price": "7,75"}, 
  {"id_product": "100000339", "d_price": "9,76"}]'
);

o_product   o_price
100000158   7,75
100000339   9,76

Demo

对于那些可能想做类似事情的人来说,这是一个解决方案:

我将输入更改为:{0: [100000158, 7.76], 1: [100000339, 9.76]}

和功能:

CREATE OR REPLACE FUNCTION public.check_d_price(
    p_products jsonb)
    RETURNS jsonb
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE PARALLEL UNSAFE
AS $BODY$
DECLARE
        _key varchar;
        _real_price NUMERIC;
        _bad_price jsonb;
BEGIN

    FOR _key IN (
        SELECT jsonb_object_keys(p_products)
    )
    LOOP
        SELECT ei.price INTO _real_price FROM product pr JOIN ecom_input ei ON (pr.ecom_id,pr.sku) = (ei.ecom_id,ei.sku_supplier) WHERE pr.id = (p_products->_key->>0)::INT;
        IF _real_price <> (p_products->_key->>1)::NUMERIC THEN
                _bad_price = COALESCE(_bad_price,'{}'::jsonb) || jsonb_build_object((p_products->_key->>0)::TEXT,
                                                                                    jsonb_build_object('d_price', p_products->_key->>1,'new_price', _real_price));
        END IF;
    END LOOP;

    RETURN _bad_price;

END;
$BODY$;