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
对于那些可能想做类似事情的人来说,这是一个解决方案:
我将输入更改为:{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$;
我正在尝试创建一个以参数为参数的 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
对于那些可能想做类似事情的人来说,这是一个解决方案:
我将输入更改为:{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$;