In PostgreSQL, functions can return either a single value or a collection of rows. The SETOF keyword, used in the RETURNS clause, designates the function as a set-returning function (SRF). When invoked in the FROM clause—behaving like a virtual table—or in a LATERAL join, the function can stream multiple rows to the calling query. SETOF may be paired with a built-in scalar type (e.g., integer, text), a user-defined composite type, or RECORD. When combined with OUT parameters, the engine automatically builds an anonymous composite row type. Rows are produced with RETURN NEXT or RETURN QUERY statements inside PL/pgSQL, or by simply selecting rows in SQL-language functions. Because the caller can receive 0, 1, or many rows, SRFs integrate naturally with set-based SQL operations such as JOINs, WHERE filters, and ORDER BY. Caveats: SRFs cannot be used directly in the SELECT list after PostgreSQL 10 unless marked as explicit lateral; SRFs executed per row in a SELECT list can cause performance surprises; and SRFs run inside simple SELECT statements must be placed in the FROM clause for clarity and future compatibility.
RETURNS TABLE, RECORD type, LATERAL, UNNEST, GENERATE_SERIES, set returning functions (SRF)
PostgreSQL 7.3
RETURNS SETOF type tells PostgreSQL to stream rows of a single data type or composite type. RETURNS TABLE lets you declare column names and types inline, producing the same effect but with self-describing output.
Return a composite type: either reference an existing table type (e.g., RETURNS SETOF users) or declare OUT parameters/RECORD and provide a column list to the caller.
Yes. Because the function appears in the FROM clause, you can apply WHERE, JOIN, GROUP BY, ORDER BY, LIMIT, and window functions exactly as you would on a real table.
No. Each invocation runs the function code. To avoid repeated work, materialize results into a table or use a VIEW if parameters are not required.