Reputation: 5
I'm creating a thread-safe function. I want to have the number incremented by 'p_sitename' and 'p_sourcename'.
CREATE OR REPLACE FUNCTION public.fn_ppp(
p_sitename character varying,
p_sourcename character varying)
RETURNS integer
LANGUAGE 'plpgsql'
COST 100
VOLATILE
AS $BODY$
declare
res integer ;
begin
lock table std_seq in access exclusive mode;
update
std_seq
set
post_id = (
select
post_id + 1 into res
from
std_seq
where
sitename = p_sitename and
sourcename = p_sourcename
limit 1
)
where
sitename = p_sitename and
sourcename = p_sourcename ;
return res;
end;
$BODY$;
The error message is
ERROR: INTO used with a command that cannot return data
CONTEXT: PL/pgSQL function fn_ppp(character varying,character varying) line
8 at SQL statement
SQL state: 42601
Why not?
Upvotes: 0
Views: 1187
Reputation: 246788
SELECT ... INTO
cannot be in a subquery, only on the top level.
But you can easily do what you want with UPDATE ... RETURNING
:
UPDATE std_seq
SET post_id = post_id + 1
WHERE sitename = p_sitename
AND sourcename = p_sourcename
RETURNING post_id INTO res;
Since everything happens in one statement, there is no need to explicitly lock the table at all. Every concurrent transaction that calls the same function with the same transaction will be blocked until your transaction is done, and no duplicates can occur.
The table should have a primary key constraint on (sitename, sourcename, post_id)
. That will prevent duplicates, but may also speed up the UPDATE
.
Upvotes: 3