仅供参考:我对使用游标完全不熟悉...... 所以我有一个游标功能:
CREATE FUNCTION get_all_product_promos(refcursor, cursor_object_id integer) RETURNS refcursor AS '
BEGIN
OPEN $1 FOR SELECT *
FROM promos prom1
JOIN promo_objects ON (prom1.promo_id = promo_objects.promotion_id)
WHERE prom1.active = true AND now() BETWEEN prom1.start_date AND prom1.end_date
AND promo_objects.object_id = cursor_object_id
UNION
SELECT prom2.promo_id
FROM promos prom2
JOIN promo_buy_objects ON (prom2.promo_id =
promo_buy_objects.promo_id)
LEFT JOIN promo_get_objects ON prom2.promo_id = promo_get_objects.promo_id
WHERE (prom2.buy_quantity IS NOT NULL OR prom2.buy_quantity > 0) AND
prom2.active = true AND now() BETWEEN prom2.start_date AND
prom2.end_date AND promo_buy_objects.object_id = cursor_object_id;
RETURN $1;
END;
' LANGUAGE plpgsql;
那么我在另一个函数中调用它并需要处理它:
...
--Get the promotions from the cursor
SELECT get_all_product_promos('promo_cursor', this_object_id)
updated := FALSE;
IF FOUND THEN
--Then loop through your results
LOOP
FETCH promo_cursor into this_promotion
--Preform comparison logic -this is necessary as this logic is used in other contexts from other functions
SELECT * INTO best_promo_results FROM get_best_product_promos(this_promotion, this_object_id, get_free_promotion, get_free_promotion_value, current_promotion_value, current_promotion);
...
所以这里的想法是从光标中选择,使用fetch循环(接下来假设是正确的?)并将记录提取到this_promotion中。然后将this_promotion中的记录发送到另一个函数。我无法弄清楚在get_best_product_promos中声明this_promotion的类型。这就是我所拥有的:
CREATE OR REPLACE FUNCTION get_best_product_promos(this_promotion record, this_object_id integer, get_free_promotion integer, get_free_promotion_value numeric(10,2), current_promotion_value numeric(10,2), current_promotion integer)
RETURNS...
它告诉我:错误:plpgsql函数不能采取类型记录
好的,我先尝试过:
CREATE OR REPLACE FUNCTION get_best_product_promos(this_promotion get_all_product_promos, this_object_id integer, get_free_promotion integer, get_free_promotion_value numeric(10,2), current_promotion_value numeric(10,2), current_promotion integer)
RETURNS...
因为我在Postgres文档中看到一些语法显示正在创建一个具有类型'tablename'的输入参数的函数,这可以工作,但它必须是一个表名而不是一个函数:(我知道我是如此接近,我被告知使用游标传递记录。所以我研究了。请帮助。
答案 0 :(得分:1)
一种可能性是将get_all_product_promos中的查询定义为all_product_promos视图。然后,您将自动使用“all_product_promos%rowtype”类型在函数之间传递。
就是这样:
CREATE VIEW all_product_promos AS
SELECT promo_objects.object_id, prom1.*
FROM promos prom1
JOIN promo_objects ON (prom1.promo_id = promo_objects.promotion_id)
WHERE prom1.active = true AND now() BETWEEN prom1.start_date AND prom1.end_date
UNION ALL
SELECT promo_buy_objects.object_id, prom2.*
FROM promos prom2
JOIN promo_buy_objects ON (prom2.promo_id = promo_buy_objects.promo_id)
LEFT JOIN promo_get_objects ON prom2.promo_id = promo_get_objects.promo_id
WHERE (prom2.buy_quantity IS NOT NULL OR prom2.buy_quantity > 0)
AND prom2.active = true
AND now() BETWEEN prom2.start_date AND prom2.end_date
您应该能够使用EXPLAIN验证查询SELECT * FROM all_product_promos WHERE object_id = ?
将object_id
参数带入两个子查询,而不是之后进行过滤。然后从另一个函数你可以写:
DECLARE
this_promotion all_product_promos%ROWTYPE;
BEGIN
FOR this_promotion IN
SELECT * FROM all_product_promos WHERE object_id = this_object_id
LOOP
-- deal with promotion in this_promotion
END LOOP;
END
TBH我会避免使用游标在PLPGSQL中传递记录。实际上,我会避免在PLPGSQL中使用游标完全停止 - 除非您出于某种原因需要将整个结果集传递给另一个函数。简单地循环遍历语句的这种方法要简单得多,但需要注意的是整个结果集首先实现为内存。
此方法的另一个缺点是,如果需要向all_product_promos添加列,则需要重新创建依赖于它的所有函数,因为您无法使用“alter view”向视图添加列。 AFAICT也会影响使用CREATE TYPE
创建的命名类型,因为ALTER TYPE
似乎不允许您向类型添加列。
因此,您可以使用“CREATE TYPE”指定记录格式以在函数之间传递。任何关系都会自动指定一个名为<relation>%ROWTYPE
的类型,您也可以使用它。
答案 1 :(得分:0)
答案:
选择光标功能中的特定字段而不是*
然后:
CREATE TYPE get_all_product_promos as (buy_quantity integer, discount_amount numeric(10,2), get_quantity integer, discount_type integer, promo_id integer);
然后我可以说:
CREATE OR REPLACE FUNCTION get_best_product_promos(this_promotion get_all_product_promos, this_object_id integer, get_free_promotion integer, get_free_promotion_value numeric(10,2), current_promotion_value numeric(10,2), current_promotion integer)
RETURNS...