Ispirer Website Ispirer Toolkit Overview Free Trial

Returning Result Sets in PostgreSQL

Unlike databases such as Microsoft SQL Server or Sybase Adaptive Server Enterprise, PostgreSQL does not allow procedures to directly return result sets in the same way as a plain SELECT statement.

However, PostgreSQL provides several mechanisms to return sets of rows.

SQLWays currently supports the following approaches:

The last two options require additional configuration of our tool.
More details about this configuration can be found in the article: Configuring Result Sets Conversion option for PostgreSQL

Lets focus on the mechanisms used to return result sets in PostgreSQL.
For detailed examples of how to retrieve data from such functions and procedures, see Retrieving Data from PostgreSQL Functions and Procedures.

1. RETURNS TABLE

CREATE OR REPLACE FUNCTION get_empl_by_id(v_EmpId INTEGER)
RETURNS TABLE
(
   emp_id VARCHAR,
   first_name VARCHAR,
   last_name VARCHAR,
   salary VARCHAR
)
LANGUAGE plpgsql
AS $$
BEGIN
   RETURN QUERY
   SELECT
        empl.emp_id,
        empl.first_name,
        empl.last_name,
        empl.salary
   FROM empl
   WHERE empl.emp_id = v_EmpId;
END;
$$;

This option is convenient when a function should return a result similar to a regular SELECT query.

Advantages:

  1. SELECT
  2. CTE (WITH)
  3. subqueries
  4. other functions

Functions defined this way integrate naturally with SQL queries.
Examples of how to call such functions and retrieve their results are described in Retrieving Data from PostgreSQL Functions and Procedures.


2. RETURNS SETOF (Composite Type)

CREATE TYPE employee_info AS (
   emp_id INT,
   name TEXT,
   salary NUMERIC
);

CREATE FUNCTION get_high_sal (min_salary NUMERIC)
RETURNS SETOF employee_info
LANGUAGE plpgsql
AS $$
BEGIN
   RETURN QUERY
   SELECT
        id,
        name,
        salary
   FROM empl
   WHERE salary >= min_salary;
END;
$$;

In our tool, this approach is implemented using a composite type, which is created before the function itself.

Such functions return a set of rows and can also be used directly in:

However, this approach is generally less readable and requires first creating a composite type.

Examples of how to query functions that return SETOF values are provided in Retrieving Data from PostgreSQL Functions and Procedures.


Limitations of RETURNS TABLE and RETURNS SETOF

Both approaches share several limitations:

Note:

It is not allowed to use explicit OUT or INOUT parameters together with the RETURNS TABLE notation. All output columns must be defined inside the TABLE clause.


3. INOUT REFCURSOR

If there is a need to return multiple result sets or to retrieve results incrementally, REFCURSOR parameters can be used.

Our conversion tool supports converting such logic into a procedure that uses REFCURSOR parameters as INOUT arguments.

CREATE OR REPLACE PROCEDURE fromora.get_empl_dept(
    v_EmpId INTEGER,
    INOUT v_MinSalary DECIMAL(10,2),
    INOUT SWV_RefCur refcursor DEFAULT NULL,
    INOUT SWV_RefCur2 refcursor DEFAULT NULL
)
LANGUAGE plpgsql
AS $$
BEGIN
    -- get information about a specific employee
    OPEN SWV_RefCur FOR
    SELECT emp_id, name, salary
    FROM fromora.empl
    WHERE emp_id = v_EmpId;

    -- fill the output parameter
    SELECT salary INTO v_MinSalary
    FROM empl
    WHERE emp_id = v_EmpId
    UNION ALL
    SELECT v_MinSalary;

    -- get the list of departments
    OPEN SWV_RefCur2 FOR
    SELECT dept_id, location, region
    FROM fromora.dept;
END;
$$;

Advantages of using REFCURSOR:

Limitations:

A REFCURSOR is a reference to an open cursor that points to a query result stored on the server. To access the data, it must first be explicitly retrieved using FETCH.

Detailed examples of how to call such procedures and retrieve the data from returned cursors are provided in Retrieving Data from PostgreSQL Functions and Procedures.


If you have any questions or face any difficulties, please contact our support team at support@ispirer.com