I have a hard time understanding why I can refer to the output columns in returns table(col type)
.
There is a subtle bug in the below code, the order by
var refers to res
in returns
, not to data1
which we aliased to res
. res
in where
is always null and we get 0 rows.
Why can I refer to the column name in output?
In what cases do I want this?
CREATE OR REPLACE FUNCTION public.test(var INTEGER)
RETURNS table(res int )
LANGUAGE plpgsql
AS $function$
begin
return query
select data1 res
from table_with_data
where res < var;
end
$function$
2
Answers
Why can I refer to the column name in output
From the manual, the section about function parameters:
What this means is that in your case
res
is effectively a writeable variable, which type you plan to return a set of. As any other variable without a default value assigned, it starts off asnull
.In what case do I want this
You can return multiple records from a function of this type with a single
return query
, but another way is by a series of multiplereturn query
orreturn next
– in the second case, filling out the fields in a record of your output table each time. You could have expected a return statement to end the function, but in this scenario only a singlereturn;
without anything added would have that effect.Which is the most useful with
LOOP
sExample results
True,
OUT
parameters (including field names in aRETURNS TABLE (...)
clause) are visible in all SQL DML statements in a PL/pgSQL function body, just like other variables. Find details in the manual chapters Variable Substitution and Returning from a Function for PL/pgSQL.However, a more fundamental misunderstanding comes first here. The syntax of your nested
SELECT
is invalid to begin with. The PL/pgSQL variable happens to mask this problem (with a different problem). In SQL, you cannot refer to output column names (column aliases in theSELECT
clause) in theWHERE
clause. This is invalid:The manual:
This is different for
ORDER BY
, which you mention in the text, but don’t include in the query. See:Fixing immediate issue
Could be repaired like this:
fiddle
See:
The column alias is just noise in this case. The name of the column returned from the function is
res
in any case – as defined in theRETURNS TABLE
clause.Aside: It’s recommended not to omit the
AS
keyword for column aliases (unlike table aliases). See:If there was actual ambiguity between column and variable name – say, you declared an
OUT
parameter or variable nameddata1
– you’d get an error message like this:Brute force fix
Could be fixed with a special command at the start of the function body:
See:
Proper fix
Table-qualify column names, and avoid conflicting variable names to begin with.
Example: