Summary: in this tutorial, you’ll learn how to use the PL/pgSQL Record data type to represent a row of a query.
Overview of the PL/pgSQL record type #
The RECORD data type represents a single row of a query’s result set.
Here’s the syntax for declaring a RECORD variable:
DECLARE
variable_name RECORD;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)The RECORD type variable does not have a predefined structure. It inherits the structure of the row when you assign a row to it using the SELECT INTO or FOR statement.
The following shows how to select a row from a table and assign it to the record variable:
DO $$
DECLARE
v_record RECORD;
BEGIN
SELECT select_list INTO v_record
FROM table_name
WHERE condition;
END;
$$;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)If a query returns multiple rows, you can use the FOR loop statement to assign each row of the result set to the record:
DO $$
DECLARE
v_record RECORD;
BEGIN
FOR v_record IN
SELECT select_list
FROM table_name
WHERE condition
LOOP
-- processing each row
END LOOP;
END;
$$;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)It is important to note that RECORD is not a valid data type but a placeholder.
To access a field in a record, you use the dot notation syntax as follows:
v_record.field_nameCode language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Note that you can only access a field of a record after assigning a row to it.
Basic PL/pgSQL record type example #
The following example defines a function called get_price() that returns the price of product specified by an id:
CREATE FUNCTION get_price(id INT) RETURNS DEC
AS
$$
DECLARE
v_product RECORD;
BEGIN
SELECT product_name, price
INTO v_product
FROM products
WHERE product_id = id;
IF FOUND THEN
RETURN v_product.price;
ELSE
RETURN NULL;
END IF;
END;
$$
LANGUAGE plpgsql;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)How it works
First, declare a record variable v_product with the type RECORD:
DECLARE v_product RECORD;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Second, retrieve the row from the products table with the product_id 1 and assign it to the v_product record variable:
SELECT product_name, price
INTO v_product
FROM products
WHERE product_id = 1;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Finally, return the the product price if the product exists or NULL otherwise:
IF FOUND THEN
RETURN v_product.price;
ELSE
RETURN NULL;
END IF;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)You can call the get_price function to retrieve the price of the product with id 1:
SELECT get_price(1);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Output:
get_price
-----------
999.99Code language: plaintext (plaintext)Using a RECORD variable with a FOR loop #
The following shows how to select the top three most expensive products and print them on the screen:
DO $$
DECLARE
v_product RECORD;
BEGIN
FOR v_product IN SELECT product_name, price
FROM products
ORDER BY price DESC, product_name LIMIT 3
LOOP
RAISE NOTICE '%: $%', v_product.product_name, v_product.price;
END LOOP;
END;
$$;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)How it works:
First, declare a variable with the type RECORD in the declaration section:
DECLARE v_product RECORD;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Second, use a FOR statement to retrieve the top 3 most expensive products and assign each to the record variable:
FOR v_product IN SELECT product_name, price
FROM products
ORDER BY price DESC, product_name LIMIT 3Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Third, display the product name and price in each iteration of the loop:
RAISE NOTICE '%: $%', v_product.product_name, v_product.price;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Dynamic query execution with RECORD #
To execute a dynamic query, you use the EXECUTE statement:
EXECUTE query;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)In this syntax, the query is a literal string representing a query to execute.
When you execute a dynamic query, you only know the structure of the result set at runtime. In this case, a RECORD variable is ideal for handling the dynamic result.
Here’s the syntax for executing a dynamic query and assigning the row to a record:
EXECUTE query INTO record_variable;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)The following example defines a function get_record that executes a dynamic query and returns a record.
CREATE FUNCTION get_record (query TEXT)
RETURNS RECORD AS $$
DECLARE
rec RECORD;
BEGIN
EXECUTE query INTO rec;
RETURN rec;
END;
$$ LANGUAGE plpgsql;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)To call the get_record function, you need to cast the record explicitly into a specific type:
SELECT
*
FROM
get_record (
'SELECT product_name, price FROM products WHERE product_id = 1'
) AS product_info (product_name VARCHAR, price DEC);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Output:
product_name | price
--------------------+--------
Samsung Galaxy S24 | 999.99Code language: plaintext (plaintext)Summary #
- Use the PL/pgSQL
RECORDdata type to handle rows without a predefined structure. - Use
SELECT INTOandFORloops to assign rows to a record. - Use the dot notation (e.g.,
record_variable.field_name) to access individual fields of a record. - Use
RECORDvariable for dynamic query where the row structure is known only at runtime.