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;
并在上面的插入查询中使用它。
最好的方法是什么?
那就是
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
在这里毫无意义。
有关在 PL/pgSQL 中分配变量的基础知识:
除此之外,您的函数还存在许多语法错误和其他问题。开始于:
CREATE OR REPLACE FUNCTION "freeTicket" (eid integer NOT NULL)
DECLARE ...
NOT NULL
此处无效语法。
您必须以某种方式声明返回类型。如果函数没有返回任何内容,请添加 RETURNS void
。
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 ...
。但不需要别名,因为声明中没有歧义。相关:
purchase
和
purchases
的表,这肯定会导致混乱。第二个表也可能替换为 VIEW
或
MATERIALIZED VIEW
。