Reputation: 4582
My aim is to write a function that takes in one parameter and returns two values. The query is working perfectly, however, when executed via the function made, I receive an error that a subquery should not return multiple columns.
My function is as follows:
CREATE TYPE double_integer_type AS (p1 integer, p2 integer);
DROP FUNCTION next_dvd_in_queue;
CREATE OR REPLACE FUNCTION next_dvd_in_queue (member_id_p1 integer) RETURNS double_integer_type as $$
BEGIN
RETURN(
select temp2.dvdid,
temp2.movie_title
from
(select temp1.dvdid,
temp1.movie_title,
temp1.customer_priority
from
(select *
from rentalqueue
where rentalqueue.memberid=member_id_p1) temp1
inner join dvd on dvd.dvdid=temp1.dvdid
where dvd.dvdquantityonhand>0) temp2
order by temp2.customer_priority asc
limit 1
);
END; $$ LANGUAGE PLPGSQL
Call:
select dvdid from next_dvd_in_queue(3);
The query, when executed with a hard-coded value, is:
select temp2.dvdid,
temp2.movie_title
from
(select temp1.dvdid,
temp1.movie_title,
temp1.customer_priority
from
(select *
from rentalqueue
where rentalqueue.memberid=3) temp1
inner join dvd on dvd.dvdid=temp1.dvdid
where dvd.dvdquantityonhand>0) temp2
order by temp2.customer_priority asc
limit 1
The above query works fine.
However, when I call the function in the following way:
select * from next_dvd_in_queue(3);
I get the following error:
ERROR: subquery must return only one column LINE 1: SELECT ( ^ QUERY: SELECT ( select temp2.dvdid, temp2.movie_title from (select temp1.dvdid, temp1.movie_title, temp1.customer_priority from (select * from rentalqueue where rentalqueue.memberid=3) temp1 inner join dvd on dvd.dvdid=temp1.dvdid where dvd.dvdquantityonhand>0) temp2 order by temp2.customer_priority asc limit 1 ) CONTEXT: PL/pgSQL function next_dvd_in_queue(integer) line 3 at RETURN
Upvotes: 0
Views: 1222
Reputation: 658472
You can fix the syntax error with an explicit cast to the composite type:
CREATE OR REPLACE FUNCTION next_dvd_in_queue (member_id_p1 integer)
RETURNS double_integer_type AS
$func$
BEGIN
RETURN (
SELECT ROW(temp2.dvdid, temp2.movie_title)::double_integer_type
FROM ...
);
END
$func$ LANGUAGE plpgsql
But I would remove the needless complication with the composite type and use OUT
parameters instead:
CREATE OR REPLACE FUNCTION pg_temp.next_dvd_in_queue (member_id_p1 integer
OUT p1 integer
OUT p2 varchar(100)) AS
$func$
BEGIN
SELECT INTO p1, p2
temp2.dvdid, temp2.movie_title
FROM ...
END
$func$ LANGUAGE plpgsql;
Avoid naming collisions between parameter names and column names. I like to stick to a naming convention where I prefix all parameter names with _
, so _member_id_p1
, _p1
, _p2
.
Related:
Upvotes: 1