我有一个存储过程,可以插入,更新或删除表行。当所有参数都用作输入时,它运行良好。但是,我需要返回最后插入的行的ID。为此,我尝试使用INOUT
参数和RETURNING
语句后的INSERT
返回ID。
但是,我不确定如何将返回的ID绑定到INOUT
参数。以下是存储过程的代码:
CREATE OR REPLACE PROCEDURE public.spproductinsertupdatedelete(
_ser integer,
_subcategid integer,
_inrprice numeric,
_usdprice numeric,
_colour integer,
_size integer,
_qty integer,
_prodid integer DEFAULT NULL::integer,
inout _pid integer default null
)
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
if _ser=1 then --- Insert
INSERT INTO product (prod_subcateg_id,prod_inr_price,prod_usd_price,prod_colour,prod_size,prod_qty)
VALUES (_subcategID, _inrprice, _usdprice, _colour, _size, _qty)
RETURNING prod_id;
ELSEIF _ser=2 THEN
UPDATE PRODUCT SET
prod_subcateg_id = _subcategid,
prod_inr_price = _inrprice,
prod_usd_price = _usdprice,
prod_size = _size,
prod_colour = _colour,
prod_qty=_qty
where prod_id = _prodID;
ELSEIF _ser=3 THEN ---- Delete
UPDATE PRODUCT SET prod_datetill = now()
WHERE prod_id = _prodID;
end if;
END
$BODY$;
在执行上述存储过程时,我收到此错误:
ERROR: query has no destination for result data
答案 0 :(得分:1)
PROCEDURE
可以返回值,但是返回值非常有限(自Postgres 13起)。
CALL
执行一个过程。如果该过程具有任何输出参数,则结果行将为 返回,其中包含这些参数的值。
The manual on CREATE PROCEDURE
:
argmode
自变量的模式:
IN
,INOUT
或VARIADIC
。如果省略,则默认值为IN
。 (过程目前不支持OUT
自变量。请改为使用INOUT
。)
因此,您对INOUT
模式的使用是正确的。但是缺少功能体中的分配。还有其他一些事情是错误的/次优的。我建议:
CREATE OR REPLACE PROCEDURE public.spproductinsertupdatedelete(
_ser int
, _subcategid int
, _inrprice numeric
, _usdprice numeric
, _colour int
, _size int
, _qty int
, INOUT _prod_id int DEFAULT NULL
)
LANGUAGE plpgsql AS
$proc$
BEGIN
CASE _ser -- simpler than IF
WHEN 1 THEN -- INSERT
INSERT INTO product
(prod_subcateg_id, prod_inr_price, prod_usd_price, prod_colour, prod_size, prod_qty)
VALUES (_subcategid , _inrprice , _usdprice , _colour , _size , _qty )
RETURNING prod_id
INTO _prod_id; -- !!!
WHEN 2 THEN -- UPDATE
UPDATE product
SET (prod_subcateg_id, prod_inr_price, prod_usd_price, prod_size, prod_colour, prod_qty)
= (_subcategid , _inrprice , _usdprice , _size , _colour , _qty)
WHERE prod_id = _prod_id;
WHEN 3 THEN -- soft-DELETE
UPDATE product
SET prod_datetill = now()
WHERE prod_id = _prod_id;
ELSE
RAISE EXCEPTION 'Unexpected _ser value: %', _ser;
END CASE;
END
$proc$;
db <>提琴here
以此作为概念证明。但是,我认为问题没有任何内容可以保证首先使用PROCEDURE
。
FUNCTION
FUNCTION
提供了更多返回值的选项,不需要与CALL
分开运行,并且可以集成到更大的查询中。首先,这就是您想要的,而您只是被广泛使用的错误的“存储过程”误导了。参见:
此外,在当前形式下,如果要更新或软删除一行,则必须提供许多噪声参数。普通的SQL命令可以完成这项工作。或单独的功能...
经验法则:如果不需要从内部管理事务,则可能要使用函数而不是过程。以后,可以将Postgres过程扩展为能够并返回多个结果集(根据SQL标准),但尚未返回(第13页)。
请参阅: