2

Here's a table:

CREATE TABLE t_heights (id INT, height REAL);
INSERT INTO t_heights VALUES (1,53.63), (2,45.19), (3,47.06);

Reading through the table rows with a FOR...LOOP and a RECORD type variable like this works:

CREATE OR REPLACE FUNCTION fnct_row_by_row (input_table regclass) 
RETURNS VOID
LANGUAGE plpgsql
AS $$
DECLARE
 current_row RECORD;
BEGIN
FOR current_row IN EXECUTE 'SELECT * FROM '||input_table
 LOOP
 RAISE NOTICE 'field value: %',current_row.height; -- *<<< hardcoded field name*
 END LOOP;
END;
$$
;

Results:

SELECT fnct_row_by_row ('t_heights') ;
NOTICE: field value: 53.63
NOTICE: field value: 45.19
NOTICE: field value: 47.06

However, the field extracted from the RECORD variable needs to have its name hardcoded.

How to specify dynamically the field to be extracted?

The following generates an error:

CREATE OR REPLACE FUNCTION fnct_row_by_row2 (input_table regclass, input_field_name TEXT) 
RETURNS VOID
LANGUAGE plpgsql
AS $$
DECLARE
 current_row RECORD;
BEGIN
FOR current_row IN EXECUTE 'SELECT * FROM '||input_table
 LOOP
 RAISE NOTICE 'specified field: %',current_row.input_field_name; -- *<<< field name from parameter*
 END LOOP;
END;
$$
;

Execution:

SELECT fnct_row_by_row2 ('t_heights','height') ;
ERROR: record "current_row" has no field "input_field_name"
CONTEXTE : SQL statement "SELECT current_row.input_field_name"
PL/pgSQL function fnct_row_by_row2(regclass,text) line 10 at RAISE
asked Jan 24, 2018 at 21:58
0

1 Answer 1

0

Just do

 RAISE NOTICE 'specified field: %', input_field_name;

It's already a variable at the top. That will work if you want the column/field name. If you want the column's value you'll need to use something that provides a dynamic accessor to a row type. For that, you need.

  • jsonb (as mentioned in the comments by Abelisto)
  • hstore

That said, This whole thing is a really bad idea. When possible, you should just create a function that processes a scalar and run it over the result set.

CREATE FUNCTION f(a text)
RETURNS text
AS $$
 SELECT 'foo' + a;
$$ LANGUAGE sql;
SELECT f(x) FROM t;

Rather than doing something that's more complex and statically types the table name burried within.

CREATE FUNCTION fThatOpensACursor(col text)
RETURNS SETOF text
AS $$
 SELECT to_jsonb(t)->>col
 FROM statically_typed_table AS t;
$$ LANGUAGE sql;
SELECT fThatOpensACursor('t.myCol');
answered Jan 24, 2018 at 22:02
1
  • My example was just a part, for clarity, of a larger function where I loop through each row of a table and use some of the columns' values from that row to compare to a second table and return each time a new computed dataset. Thanks for your suggestion, but it's not clear to me how it applies. Commented Jan 26, 2018 at 15:11

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.