I have some questions regarding the example for table functions in PostgreSQL manual:
CREATE TABLE foo (fooid int, foosubid int, fooname text);
CREATE FUNCTION getfoo(int) RETURNS SETOF foo AS $$
SELECT * FROM foo WHERE fooid = $1;
$$ LANGUAGE SQL;
SELECT * FROM foo
WHERE foosubid IN (
SELECT foosubid
FROM getfoo(foo.fooid) z
WHERE z.fooid = foo.fooid
);
How is this particular nested SELECT
statement different, including subtle things, from SELECT * FROM foo
? How is this particular statement useful?
How is getfoo(foo.fooid)
able to know the value of foo.fooid
? Does a function always iterate through all values when we pass in an argument like table.column
?
including subtle things
The query's is useless - other than to demonstrate syntax and functionality. It burns down to just SELECT * FROM foo
- except that it eliminates rows with null values in fooid
or foosubid
. So the actual simple equivalent is:
SELECT * FROM foo
WHERE fooid IS NOT NULL
AND foosubid IS NOT NULL;
If the table would have NOT NULL
constraints (incl. the implicit constraint of a PK), there would be no effective difference other than performance.
The scope of the subquery in the IN
expression extends to the main query, where foo
is listed in the FROM
clause. Effectively an implicit LATERAL
subquery, where the subquery is executed once for every row in the main query. The manual:
Subqueries appearing in
FROM
can be preceded by the key wordLATERAL
. This allows them to reference columns provided by precedingFROM
items. (WithoutLATERAL
, each subquery is evaluated independently and so cannot cross-reference any otherFROM
item.)Table functions appearing in
FROM
can also be preceded by the key wordLATERAL
, but for functions the key word is optional; the function's arguments can contain references to columns provided by precedingFROM
items in any case.
See: