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;
I need to set the variable of couponCode
to the output of:
Select code from couponCode where eid = $1 and percentage = 100;
And use it in the insert query above.
What is the best way to do this?
答案 0 :(得分:1)
That would be SELECT <expressions> INTO <variables> FROM ...
, but you can do it all in one statement:
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
makes no sense here.
答案 1 :(得分:0)
关于在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 p (cid, pdate, eid, ccode)
但是INSERT
statements require the AS
keyword for aliases以避免歧义(与其他DML语句不同)。所以:INSERT INTO purchases AS p ...
。但不需要别名,因为声明中没有歧义。
相关:
旁白:两个名为purchase
和purchases
的表格,必然会导致混淆。第二个表格也可以替换为VIEW
或MATERIALIZED VIEW
。