Sample Header Ad - 728x90

Procedure with nested FOR loop to update rows

1 vote
2 answers
243 views
I am trying to write a Postgres procedure in pgAdmin. The procedure I've written fails with different error messages depending on where I put the cursor. It even sometimes seems to succeed, but with no procedure created. My questions: 1. What is wrong with my code? 2. Is there a better/simpler way to achieve the same thing? The below code tries to iterate through a table of values (outer loop), and for each row in that table, to iterate through another table that has some missing values (inner loop). Whenever a missing value is found in the inner loop table, if a value that can be used exists in the outer table, I update the inner table with that value. ~~~pgsql CREATE OR REPLACE PROCEDURE impute() LANGUAGE plpgsql AS $$ DECLARE cntry_dec_means RECORD; table_row RECORD; BEGIN > FOR cntry_dec_means IN SELECT * FROM country_decade_means LOOP -- if all imputed values are null, don't do anything and move to the next row IF ISNULL(cntry_dec_means.gdppc) AND ISNULL(cntry_dec_means.gdp) AND ISNULL(cntry_dec_means.ed_gdp) AND ISNULL(cntry_dec_means.population) THEN CONTINUE; -- get matching rows from the actual table > FOR table_row IN SELECT * FROM inls625_impute WHERE country = cntry_dec_means.country AND decade = cntry_dec_means.decade LOOP IF (table_row.gdppc IS NULL) AND (cntry_dec_means.gdppc IS NOT NULL) THEN UPDATE inls625_impute SET gdppc = cntry_dec_means.gdppc WHERE inls625_impute.country = cntry_dec_means.country AND inls625_impute.decade = cntry_dec_means.decade; END LOOP; --> END LOOP; --> END; $$; ~~~ #### Update Thanks too @prasad for clarifying how to use loop labels. Unfortunately, it does not seem to work for me. Here are the errors (in psql): ~~~pgsql CREATE OR REPLACE PROCEDURE impute() LANGUAGE plpgsql AS $$" LINE 1: $$; ^ INLS-623-Labs=# table_row RECORD; ERROR: syntax error at or near "table_row" LINE 1: table_row RECORD; ^ INLS-623-Labs=# BEGIN INLS-623-Labs-# > INLS-623-Labs-# FOR cntry_dec_means IN INLS-623-Labs-# SELECT * FROM country_decade_means INLS-623-Labs-# LOOP INLS-623-Labs-# -- if all imputed values are null, don't do anything and move to the next row INLS-623-Labs-# IF ISNULL(cntry_dec_means.gdppc) INLS-623-Labs-# AND ISNULL(cntry_dec_means.gdp) INLS-623-Labs-# AND ISNULL(cntry_dec_means.ed_gdp) INLS-623-Labs-# AND ISNULL(cntry_dec_means.population) THEN INLS-623-Labs-# CONTINUE outer_loop; ERROR: syntax error at or near "> ^ INLS-623-Labs=# INLS-623-Labs=# -- get matching rows from the actual table INLS-623-Labs=# > INLS-623-Labs-# FOR table_row IN INLS-623-Labs-# SELECT * FROM inls625_impute INLS-623-Labs-# WHERE country = cntry_dec_means.country INLS-623-Labs-# AND decade = cntry_dec_means.decade INLS-623-Labs-# LOOP INLS-623-Labs-# IF ISNULL(table_row.gdppc) AND NOT ISNULL(cntry_dec_means.gdppc) THEN INLS-623-Labs-# UPDATE inls625_impute SET gdppc = cntry_dec_means.gdppc INLS-623-Labs-# WHERE inls625_impute.country = cntry_dec_means.country INLS-623-Labs-# AND inls625_impute.decade = cntry_dec_means.decade; ERROR: syntax error at or near "> ^ INLS-623-Labs=# END LOOP inner_loop; ERROR: syntax error at or near "LOOP" LINE 1: END LOOP inner_loop; ^ INLS-623-Labs=# END LOOP outer_loop; ERROR: syntax error at or near "LOOP" LINE 1: END LOOP outer_loop; ^ INLS-623-Labs=# END; WARNING: there is no transaction in progress COMMIT INLS-623-Labs=# $$; INLS-623-Labs$# ~~~ What's more, I reproduced the example provided by @prasad and get similar errors: ~~~pgsql CREATE OR REPLACE PROCEDURE t_proc() LANGUAGE plpgsql AS $$" LINE 1: $$; ^ INLS-623-Labs=# t2_rec RECORD; ERROR: syntax error at or near "t2_rec" LINE 1: t2_rec RECORD; ^ INLS-623-Labs=# BEGIN INLS-623-Labs-# > INLS-623-Labs-# FOR t_rec IN INLS-623-Labs-# SELECT * FROM t INLS-623-Labs-# LOOP INLS-623-Labs-# IF t_rec.name IS NULL AND t_rec.data IS NULL THEN INLS-623-Labs-# CONTINUE outer_loop; ERROR: syntax error at or near "> ^ INLS-623-Labs=# END IF; ERROR: syntax error at or near "IF" LINE 1: END IF; ^ INLS-623-Labs=# RAISE NOTICE 't.id value: %', t_rec.id; ERROR: syntax error at or near "RAISE" LINE 1: RAISE NOTICE 't.id value: %', t_rec.id; ^ INLS-623-Labs=# > INLS-623-Labs-# FOR t2_rec IN INLS-623-Labs-# SELECT * FROM t2 WHERE t2.id = t_rec.id INLS-623-Labs-# LOOP INLS-623-Labs-# RAISE NOTICE 't2.id value: %', t2_rec.id; ERROR: syntax error at or near "> ^ INLS-623-Labs=# END LOOP inner_loop; ERROR: syntax error at or near "LOOP" LINE 1: END LOOP inner_loop; ^ INLS-623-Labs=# END LOOP outer_loop; ERROR: syntax error at or near "LOOP" LINE 1: END LOOP outer_loop; ^ INLS-623-Labs=# END; WARNING: there is no transaction in progress COMMIT INLS-623-Labs=# $$; ~~~
Asked by bellysavalas (13 rep)
Nov 12, 2024, 02:57 AM
Last activity: Nov 12, 2024, 07:06 PM