<command>RETURN NEXT</command> or <command>RETURN
QUERY</command> commands are executed, the result set is built
up. A final <command>RETURN</command>, which should have no
argument, causes control to exit the function (or you can just
let control reach the end of the function).
</para>
<para>
<command>RETURN QUERY</command> has a variant
<command>RETURN QUERY EXECUTE</command>, which specifies the
query to be executed dynamically. Parameter expressions can
be inserted into the computed query string via <literal>USING</literal>,
in just the same way as in the <command>EXECUTE</command> command.
</para>
<para>
If you declared the function with output parameters, write just
<command>RETURN NEXT</command> with no expression. On each
execution, the current values of the output parameter
variable(s) will be saved for eventual return as a row of the
result. Note that you must declare the function as returning
<literal>SETOF record</literal> when there are multiple output
parameters, or <literal>SETOF <replaceable>sometype</replaceable></literal>
when there is just one output parameter of type
<replaceable>sometype</replaceable>, in order to create a set-returning
function with output parameters.
</para>
<para>
Here is an example of a function using <command>RETURN
NEXT</command>:
<programlisting>
CREATE TABLE foo (fooid INT, foosubid INT, fooname TEXT);
INSERT INTO foo VALUES (1, 2, 'three');
INSERT INTO foo VALUES (4, 5, 'six');
CREATE OR REPLACE FUNCTION get_all_foo() RETURNS SETOF foo AS
$BODY$
DECLARE
r foo%rowtype;
BEGIN
FOR r IN
SELECT * FROM foo WHERE fooid > 0
LOOP
-- can do some processing here
RETURN NEXT r; -- return current row of SELECT
END LOOP;
RETURN;
END;
$BODY$
LANGUAGE plpgsql;
SELECT * FROM get_all_foo();
</programlisting>
</para>
<para>
Here is an example of a function using <command>RETURN
QUERY</command>:
<programlisting>
CREATE FUNCTION get_available_flightid(date) RETURNS SETOF integer AS
$BODY$
BEGIN
RETURN QUERY SELECT flightid
FROM flight
WHERE flightdate >= $1
AND flightdate < ($1 + 1);
-- Since execution is not finished, we can check whether rows were returned
-- and raise exception if not.
IF NOT FOUND THEN
RAISE EXCEPTION 'No flight at %.', $1;
END IF;
RETURN;
END;
$BODY$
LANGUAGE plpgsql;
-- Returns available flights or raises exception if there are no
-- available flights.
SELECT * FROM get_available_flightid(CURRENT_DATE);
</programlisting>
</para>
<note>
<para>
The current implementation of <command>RETURN NEXT</command>
and <command>RETURN QUERY</command> stores the entire result set
before returning from the function, as discussed above. That
means that if a <application>PL/pgSQL</application> function produces a
very large result set, performance might be poor: data will be
written to disk to avoid memory exhaustion, but the function
itself will not return until the entire result set has been
generated. A future version of <application>PL/pgSQL</application> might
allow users to define set-returning functions
that do not have this limitation. Currently, the point at
which data begins being written to disk is controlled by the
<xref linkend="guc-work-mem"/>
configuration variable. Administrators who have sufficient
memory to store larger result sets in memory should consider
increasing this parameter.
</para>
</note>
</sect3>
</sect2>
<sect2 id="plpgsql-statements-returning-procedure">
<title>Returning from a Procedure</title>
<para>
A procedure does not have a return value. A procedure can therefore end