【问题标题】:Setting variable in a Postgres function在 Postgres 函数中设置变量
【发布时间】:2018-03-25 19:23:05
【问题描述】:
CREATE OR REPLACE FUNCTION "freeTicket" (eid integer NOT NULL)

DECLARE
    couponCode text 
BEGIN


INSERT INTO purchases p (cid, pdate, eid, ccode) 
VALUES
(
  SELECT p.cid, GETDATE(), $1, couponCode FROM purchase p
  GROUP BY p.cid
 HAVING COUNT(1) > 5
  ORDER BY p.cid
);

END; LANGUAGE plpgsql;

我需要将couponCode的变量设置为:

Select code from couponCode where eid = $1 and percentage = 100; 

并在上面的插入查询中使用它。
最好的方法是什么?

【问题讨论】:

    标签: sql postgresql function variable-assignment plpgsql


    【解决方案1】:

    那就是SELECT <expressions> INTO <variables> FROM ...,但您可以在一个语句中完成所有操作:

    INSERT INTO purchases p (cid, pdate, eid, ccode) 
       SELECT p.cid,
              current_date,
              $1,
              (SELECT code FROM couponcode
               WHERE eid = $1 AND percentage = 100)
       FROM purchase p
       GROUP BY p.cid
       HAVING COUNT(1) > 5:
    

    ORDER BY 在这里毫无意义。

    【讨论】:

      【解决方案2】:

      关于在 PL/pgSQL 中分配变量的基础知识:

      除此之外,您的函数还有许多语法错误和其他问题。开始于:

      CREATE OR REPLACE FUNCTION "freeTicket" (eid integer NOT NULL)
      
      DECLARE ...
      • NOT NULL 此处的语法无效。
      • 您必须以某种方式声明返回类型。如果函数没有返回任何内容,请添加RETURNS void
      • 为了您自己的利益,请避免在 Postgres 中使用 CaMeL 大小写标识符。如果可能,仅使用合法的小写标识符。见:

      函数的工作原理如下:

      CREATE OR REPLACE FUNCTION free_ticket(_eid integer, OUT _row_ct int) AS
      $func$
      DECLARE
         coupon_code text;  -- semicolon required
      BEGIN
         INSERT INTO purchases (cid, pdate, eid, ccode)
         SELECT cid, now()::date, _eid
             , (SELECT code FROM couponCode WHERE eid = _eid AND percentage = 100)
         FROM   purchase
         GROUP  BY cid
         HAVING COUNT(*) > 5  -- count(*) is faster
         ORDER  BY cid;       -- ORDER BY is *not* pointless.
      
         GET DIAGNOSTICS _row_ct := ROW_COUNT;
      END
      $func$  LANGUAGE plpgsql;
      

      添加的OUT row_ct int在函数结束时自动返回。它消除了对显式 RETURNS 声明的需要。

      您还有一个表别名:

      INSERT INTO purchases <b>p</b> (cid, pdate, eid, ccode)

      INSERT statements require the AS keyword for aliases 是为了避免歧义(与其他 DML 语句不同)。所以:INSERT INTO purchases AS p ...。但不需要别名,因为声明中没有歧义。

      相关:

      旁白:两个表名为purchasepurchases,这势必会导致混乱。第二个表也可能被替换为VIEWMATERIALIZED VIEW

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-03-09
        • 2020-07-31
        • 1970-01-01
        • 1970-01-01
        • 2016-05-21
        • 2015-07-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多