Functions returning TABLE let you get multiple rows and columns as a result. They help organize complex queries into reusable blocks.
Functions returning TABLE in PostgreSQL
Start learning this pattern below
Jump into concepts and practice - no test required
or
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction
Syntax
PostgreSQL
CREATE FUNCTION function_name(parameters) RETURNS TABLE(column1 datatype, column2 datatype, ...) AS $$ BEGIN RETURN QUERY SELECT ...; END; $$ LANGUAGE plpgsql;
The RETURNS TABLE clause defines the columns and their types the function will return.
Use RETURN QUERY to return the rows from a SELECT statement inside the function.
Examples
PostgreSQL
CREATE FUNCTION get_users() RETURNS TABLE(id INT, name TEXT) AS $$ BEGIN RETURN QUERY SELECT user_id, user_name FROM users; END; $$ LANGUAGE plpgsql;
PostgreSQL
CREATE FUNCTION get_orders_by_customer(cust_id INT) RETURNS TABLE(order_id INT, amount NUMERIC) AS $$ BEGIN RETURN QUERY SELECT id, total FROM orders WHERE customer_id = cust_id; END; $$ LANGUAGE plpgsql;
Sample Program
This example creates a table of employees, inserts some data, then defines a function that returns employees by department. Finally, it calls the function to get employees in the 'IT' department.
PostgreSQL
CREATE TABLE employees ( emp_id SERIAL PRIMARY KEY, emp_name TEXT, department TEXT ); INSERT INTO employees (emp_name, department) VALUES ('Alice', 'HR'), ('Bob', 'IT'), ('Carol', 'IT'); CREATE FUNCTION get_employees_by_dept(dept TEXT) RETURNS TABLE(emp_id INT, emp_name TEXT) AS $$ BEGIN RETURN QUERY SELECT emp_id, emp_name FROM employees WHERE department = dept; END; $$ LANGUAGE plpgsql; SELECT * FROM get_employees_by_dept('IT');
Important Notes
Functions returning TABLE are useful for returning multiple rows and columns without creating temporary tables.
Use RETURN QUERY inside the function to return the result of a SELECT statement.
You can call these functions in the FROM clause like a table.
Summary
Functions returning TABLE return multiple rows and columns as a result.
Define the output columns and types in RETURNS TABLE clause.
Use RETURN QUERY to return SELECT results inside the function.
Practice
1. What does a PostgreSQL function declared with
RETURNS TABLE do?easy
Solution
Step 1: Understand the purpose of RETURNS TABLE
TheRETURNS TABLEclause defines that the function will return a set of rows with specified columns, like a table.Step 2: Compare with other return types
Unlike scalar returns or void,RETURNS TABLEreturns multiple rows and columns.Final Answer:
Returns multiple rows and columns as a table result -> Option CQuick Check:
RETURNS TABLE means multiple rows/columns [OK]
Hint: RETURNS TABLE means function outputs rows and columns [OK]
Common Mistakes:
- Thinking RETURNS TABLE returns a single value
- Confusing RETURNS TABLE with RETURNS VOID
- Assuming it returns JSON automatically
2. Which of the following is the correct syntax to declare a PostgreSQL function returning a table with columns
id INT and name TEXT?easy
Solution
Step 1: Check RETURNS TABLE syntax
CREATE FUNCTION f() RETURNS TABLE(id INT, name TEXT) AS $$ BEGIN RETURN QUERY SELECT 1, 'a'; END; $$ LANGUAGE plpgsql; correctly declaresRETURNS TABLE(id INT, name TEXT)matching the column names and types.Step 2: Verify RETURN QUERY usage
CREATE FUNCTION f() RETURNS TABLE(id INT, name TEXT) AS $$ BEGIN RETURN QUERY SELECT 1, 'a'; END; $$ LANGUAGE plpgsql; usesRETURN QUERY SELECT 1, 'a';which returns rows matching the table structure.Final Answer:
Correct RETURNS TABLE syntax and return statement -> Option DQuick Check:
RETURNS TABLE with matching columns and RETURN QUERY [OK]
Hint: RETURNS TABLE needs column names/types and RETURN QUERY [OK]
Common Mistakes:
- Using RETURNS SETOF RECORD without column definition
- Swapping column types in RETURNS TABLE
- Returning scalar instead of query
3. Given this function:
What will be the output of
CREATE FUNCTION get_numbers() RETURNS TABLE(num INT) AS $$ BEGIN RETURN QUERY SELECT generate_series(1,3); END; $$ LANGUAGE plpgsql;
What will be the output of
SELECT * FROM get_numbers();?medium
Solution
Step 1: Understand generate_series(1,3)
This function generates rows with values 1, 2, and 3.Step 2: RETURN QUERY returns all rows
The function returns all rows fromgenerate_series(1,3)as a table with columnnum.Final Answer:
3 rows with values 1, 2, 3 -> Option AQuick Check:
generate_series(1,3) returns 3 rows [OK]
Hint: generate_series returns multiple rows, so function returns them all [OK]
Common Mistakes:
- Thinking it returns a single row
- Confusing RETURNS TABLE with scalar return
- Expecting an error due to missing RETURNS SETOF
4. Identify the error in this function:
CREATE FUNCTION get_data() RETURNS TABLE(id INT, val TEXT) AS $$ BEGIN RETURN SELECT 1, 'a'; END; $$ LANGUAGE plpgsql;
medium
Solution
Step 1: Check RETURN statement in RETURNS TABLE function
In PL/pgSQL, to return rows from a query, useRETURN QUERY, not justRETURN.Step 2: Identify missing RETURN QUERY
The function usesRETURN SELECTwhich is invalid syntax; it should beRETURN QUERY SELECT.Final Answer:
Missing RETURN QUERY before SELECT -> Option AQuick Check:
Use RETURN QUERY to return rows in RETURNS TABLE [OK]
Hint: Use RETURN QUERY, not RETURN, to return table rows [OK]
Common Mistakes:
- Using RETURN instead of RETURN QUERY for table results
- Omitting LANGUAGE plpgsql
- Incorrect RETURNS TABLE column types
5. You want to create a function that returns a table of user IDs and their uppercase names from a
users table with columns id INT and name TEXT. Which function definition correctly achieves this?hard
Solution
Step 1: Match RETURNS TABLE columns with SELECT output
The function returnsid INTandname TEXT, so the SELECT must output these types. CREATE FUNCTION get_upper_users() RETURNS TABLE(id INT, name TEXT) AS $$ BEGIN RETURN QUERY SELECT id, UPPER(name) FROM users; END; $$ LANGUAGE plpgsql; matches this.Step 2: Check the transformation applied
CREATE FUNCTION get_upper_users() RETURNS TABLE(id INT, name TEXT) AS $$ BEGIN RETURN QUERY SELECT id, UPPER(name) FROM users; END; $$ LANGUAGE plpgsql; usesUPPER(name)to convert names to uppercase as required.Step 3: Verify other options
CREATE FUNCTION get_upper_users() RETURNS TABLE(id INT, name TEXT) AS $$ BEGIN RETURN QUERY SELECT id, LOWER(name) FROM users; END; $$ LANGUAGE plpgsql; uses LOWER instead of UPPER, CREATE FUNCTION get_upper_users() RETURNS SETOF record AS $$ BEGIN RETURN QUERY SELECT id, UPPER(name) FROM users; END; $$ LANGUAGE plpgsql; returns SETOF record (no column definition), CREATE FUNCTION get_upper_users() RETURNS TABLE(id TEXT, name TEXT) AS $$ BEGIN RETURN QUERY SELECT id, UPPER(name) FROM users; END; $$ LANGUAGE plpgsql; mismatches id type (TEXT instead of INT).Final Answer:
Correctly returns id and uppercase name as a table -> Option BQuick Check:
RETURNS TABLE with matching columns and UPPER(name) [OK]
Hint: Match RETURNS TABLE columns and use RETURN QUERY with correct SELECT [OK]
Common Mistakes:
- Using LOWER instead of UPPER
- Mismatching column types in RETURNS TABLE
- Using SETOF record instead of RETURNS TABLE
