【问题标题】: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)

    请注意,在inventorybill_products 表中重复传递信息不是好的数据库设计。您可能应该省略 bill_prodcts.delivered 列,而是在每次需要时计算相应库存条目的总和。

    【讨论】:

      猜你喜欢
      • 2017-05-13
      • 1970-01-01
      • 1970-01-01
      • 2015-04-05
      • 2017-12-11
      • 2020-02-12
      • 2011-03-24
      • 1970-01-01
      • 2017-12-30
      相关资源
      最近更新 更多