【问题标题】:Postgresql complex logic function ( plpgsql )Postgresql 复杂逻辑函数 ( plpgsql )
【发布时间】:2020-02-04 02:34:41
【问题描述】:
好的,我有这个架构
https://dbfiddle.uk/?rdbms=postgres_10&fiddle=56b0781c13dfb545e9f07f82da6ae34d
- 每张账单都会有一堆产品保存在 bill_products 表中
- 此 bill_products 近期将随机发货更新
我需要制定一个函数来接受 jsonb 的输入
[
{
bill_id : 1,
product_id : 1,
delivered: 50
},
{
bill_id : 1,
product_id : 2,
delivered: 400
}
]
采用上述 jsonb 输入,该函数应更新 bill_products 并将其插入到 inventory 表中。此外,如果所有 bill_products 已交付,则应将 bill 表中的已批准布尔值更新为 true
我是 plpgsql 的新手,有人可以帮我解决这个问题。
【问题讨论】:
标签:
node.js
postgresql
plpgsql
pg
【解决方案1】:
我想应该这样做:
DO LANGUAGE plpgsql $$
DECLARE
input CONSTANT jsonb := '...';
delivery jsonb;
updated bill_products;
BEGIN
FOR delivery IN SELECT jsonb_array_elements(input) LOOP
UPDATE bill_products
SET delivered = delivered + (delivery->>'delivered')::numeric
WHERE bill_id = (delivery->>'bill_id')::int
AND pro_id = (delivery->>'product_id')::int
RETURNING *
INTO STRICT updated;
INSERT INTO inventory(pro_id, quantity)
VALUES (updated.pro_id, updated.delivered);
END LOOP;
UPDATE bill
SET approved = NOT EXISTS (SELECT 1
FROM bill_products
WHERE bill_products.bill_id = bill.bill_id
AND delivered < quantity)
WHERE bill_id IN (SELECT DISTINCT (d->>'bill_id')::int
FROM jsonb_array_elements(input) d);
END;
$$;
(online demo)
另外,使用纯 SQL 代替循环可能更简单:
WITH updates AS (
UPDATE bill_products
SET delivered = delivered + (delivery->>'delivered')::numeric
FROM jsonb_array_elements(input) delivery
WHERE bill_id = (delivery->>'bill_id')::int
AND pro_id = (delivery->>'product_id')::int
RETURNING pro_id, delivered
) INSERT INTO inventory(pro_id, quantity)
SELECT * FROM updates;
(online demo)
请注意,在inventory 和bill_products 表中重复传递信息不是好的数据库设计。您可能应该省略 bill_prodcts.delivered 列,而是在每次需要时计算相应库存条目的总和。