在 Postgres 函数中设置变量

问题描述 投票:0回答:2
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
2个回答
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
在这里毫无意义。


1
投票

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

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

CREATE OR REPLACE FUNCTION "freeTicket" (eid integer NOT NULL)

DECLARE ...
  • NOT NULL
    此处无效语法。

  • 您必须以某种方式声明返回类型。如果函数没有返回任何内容,请添加 RETURNS void

    
    

  • 为了您的利益着想,请避免在 Postgres 中使用 CaMeL 大小写标识符。如果可能,仅使用合法的小写标识符。参见:
  • PostgreSQL 列名区分大小写吗?

  • 该函数的工作原理如下:

CREATE OR REPLACE FUNCTION free_ticket(_eid integer, OUT _row_ct int) LANGUAGE plpgsql 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$;

添加的
OUT row_ct int

会在函数结束时自动返回。它消除了显式

RETURNS
声明的需要。
您还有一个表别名:

INSERT INTO purchases p (cid, pdate, eid, ccode)

但是 

INSERT 语句需要

AS
关键字作为别名
,以避免歧义(与其他 DML 语句不同)。所以:
INSERT INTO purchases AS p ...
。但不需要别名,因为声明中没有歧义。
相关:

    统计受plpgsql函数影响的行数
  • 旁白:两个名为
purchase

purchases
的表,这肯定会导致混乱。第二个表也可能替换为
VIEW
MATERIALIZED VIEW

© www.soinside.com 2019 - 2024. All rights reserved.