如何 return 来自存储过程(不是函数)的值?
How to return a value from a stored procedure (not function)?
我有一个存储过程可以插入、更新或删除表行。当所有参数都用作输入时,它工作正常。但是,我需要 return 最后插入行的 ID。为此,我尝试在 INSERT
语句之后使用 INOUT
参数和 RETURNING
来 return ID。
但是,我不确定如何将 returned 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
概念验证
A PROCEDURE
可以 return 值,但以非常有限的方式(从 Postgres 13 开始)。
CALL
executes a procedure.
If the procedure has any output parameters, then a result row will be
returned, containing the values of those parameters.
The manual on CREATE PROCEDURE
:
argmode
The mode of an argument: IN
, INOUT
, or VARIADIC
. If omitted, the default is IN
. (OUT
arguments are currently not supported for procedures. Use INOUT
instead.)
所以你对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<>fiddle here
以此作为概念证明。但是我在问题中看不到任何东西首先需要使用 PROCEDURE
。
你可能想要 FUNCTION
A FUNCTION
为 return 值提供了更多选项,不需要 运行 与 CALL
分开,并且可以集成到更大的查询中。很有可能,这正是您最初想要的,而您只是被广泛使用的误称“存储过程”误导了。参见:
此外,在当前的形式中,如果要更新或软删除一行,则必须提供许多噪声参数。普通 SQL 命令可能会完成这项工作。或者单独的功能...
经验法则:如果您不需要从内部管理事务,您可能希望使用函数而不是过程。稍后,Postgres 过程可能会扩展为能够 return 多个结果集(根据 SQL 标准),但目前还不能(第 13 页)。
参见:
- In PostgreSQL, what is the difference between a “Stored Procedure” and other types of functions?
- Do stored procedures run in database transaction in Postgres?
- https://www.2ndquadrant.com/en/blog/postgresql-11-server-side-procedures-part-1/#comment-72
- What are the differences between “Stored Procedures” and “Stored Functions”?
我有一个存储过程可以插入、更新或删除表行。当所有参数都用作输入时,它工作正常。但是,我需要 return 最后插入行的 ID。为此,我尝试在 INSERT
语句之后使用 INOUT
参数和 RETURNING
来 return ID。
但是,我不确定如何将 returned 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
概念验证
A PROCEDURE
可以 return 值,但以非常有限的方式(从 Postgres 13 开始)。
CALL
executes a procedure.If the procedure has any output parameters, then a result row will be returned, containing the values of those parameters.
The manual on CREATE PROCEDURE
:
argmode
The mode of an argument:
IN
,INOUT
, orVARIADIC
. If omitted, the default isIN
. (OUT
arguments are currently not supported for procedures. UseINOUT
instead.)
所以你对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<>fiddle here
以此作为概念证明。但是我在问题中看不到任何东西首先需要使用 PROCEDURE
。
你可能想要 FUNCTION
A FUNCTION
为 return 值提供了更多选项,不需要 运行 与 CALL
分开,并且可以集成到更大的查询中。很有可能,这正是您最初想要的,而您只是被广泛使用的误称“存储过程”误导了。参见:
此外,在当前的形式中,如果要更新或软删除一行,则必须提供许多噪声参数。普通 SQL 命令可能会完成这项工作。或者单独的功能...
经验法则:如果您不需要从内部管理事务,您可能希望使用函数而不是过程。稍后,Postgres 过程可能会扩展为能够 return 多个结果集(根据 SQL 标准),但目前还不能(第 13 页)。
参见:
- In PostgreSQL, what is the difference between a “Stored Procedure” and other types of functions?
- Do stored procedures run in database transaction in Postgres?
- https://www.2ndquadrant.com/en/blog/postgresql-11-server-side-procedures-part-1/#comment-72
- What are the differences between “Stored Procedures” and “Stored Functions”?