PostgreSQL has supported what are called Out (output) parameters since version 8.1.
We were surprised it has been that long since we always thought of it as a feature from 8.2+
until it recently came up for discussion on PostGIS newsgroup and we decided to investigate how
long it has been supported.
What are OUT parameters? These are parameters you define as part of the function argument
list that get returned back as part of the result. When you create functions, the arguments
are defaulted to IN parameters when not explicitly specified (which means they are passed in and not returned) which
is why you sometimes see PgAdmin do something like IN somevariable variabletype when you use
the function wizard.
You can have INOUT parameters as well which are function inputs that both get passed in, can be modified
by the function and also get returned.
As a side note - In 8.4, PostgreSQL was enhanced to allow dynamic sql RETURN QUERY using RETURN QUERY EXECUTE syntax for plpgsql queries and also
allow set returning functions being called in the SELECT part for any pl language. In prior versions,
this was only a feature of PL functions written in SQL.
8.3 introduced RETURN query which required a static sql statement, but did make things a bit easier.
One of the common use cases for using OUT parameters is to be able to return multiple outputs from a function without having
to declare a PostgreSQL type as output of the function. In this article we shall cover all variants of this. We'll just focus on sql and plpgsql for this
discussion, since we are not sure to what extent other pl languages (if at all) support IN OUT.
SQL and PLPGSQL examples of OUTPUT parameters - return single record
Below are some examples in plain SQL and their outputs.
CREATE OR REPLACE FUNCTION fn_sqltestout(param_subject text,
OUT subject_scramble text, OUT subject_char text)
AS
$$
SELECT substring($1, 1,CAST(random()*length($1) As integer)), substring($1, 1,1)
$$
LANGUAGE 'sql' VOLATILE;
SELECT (fn_sqltestout('This is a test subject')).subject_scramble;
-- Output
subject_scramble
------------------
This is a test
SELECT (fn_sqltestout('This is a test subject')).*;
--Output
subject_scramble | subject_char
----------------------+--------------
This is a test subje | T
CREATE OR REPLACE FUNCTION fn_plpgsqltestout(param_subject text,
OUT subject_scramble text, OUT subject_char text)
AS
$$
BEGIN
subject_scramble := substring($1, 1,CAST(random()*length($1) As integer));
subject_char := substring($1, 1,1);
END;
$$
LANGUAGE 'plpgsql' VOLATILE;
SQL OUTPUT parameters - return multiple records
CREATE OR REPLACE FUNCTION fn_sqltestmulti(param_subject varchar,
OUT test_id integer,
OUT test_stuff text)
RETURNS SETOF record
AS
$$
SELECT test_id, test_stuff
FROM testtable where test_stuff LIKE $1;
$$
LANGUAGE 'sql' VOLATILE;
SELECT * FROM fn_sqltestmulti('%stuff%');
test_id | test_stuff
---------+--------------------
1 | this is more stuff
2 | this is new stuff
CREATE OR REPLACE FUNCTION fn_plpgsqltestmulti(
param_subject varchar,
OUT test_id integer,
OUT test_stuff text)
RETURNS SETOF record
AS
$$
BEGIN
RETURN QUERY SELECT t.test_id , t.test_stuff
FROM testtable As t
WHERE t.test_stuff LIKE param_subject;
END;
$$
LANGUAGE 'plpgsql' VOLATILE;
INOUT parameters - return multiple records
CREATE OR REPLACE FUNCTION fn_sqltestmulti_inout(param_subject varchar,
INOUT test_id integer,
INOUT test_stuff text)
RETURNS SETOF record
AS
$$
SELECT $2 + test_id, $3 || test_stuff
FROM testtable
WHERE test_stuff LIKE $1;
$$
LANGUAGE 'sql' VOLATILE;
SELECT * FROM fn_sqltestmulti_inout('%stuff%',1, 'test');
test_id | test_stuff
---------------+------------------------
2 | testthis is more stuff
3 | testthis is new stuff
CREATE OR REPLACE FUNCTION fn_plpgsqltestmulti_inout(
param_subject varchar,
INOUT test_id integer,
INOUT test_stuff text)
RETURNS SETOF record
AS
$$
BEGIN
RETURN QUERY SELECT t.test_id + test_id , test_stuff || t.test_stuff
FROM testtable As t
WHERE t.test_stuff LIKE param_subject;
END;
$$
LANGUAGE 'plpgsql' VOLATILE;
Tracked: Apr 08, 02:28