2

I'm trying to learn PL/pgSQL by writing some simple programs. To learn about FOREACH loop, I wrote the following:

CREATE OR REPLACE FUNCTION test(int[]) RETURNS void AS $$  
DECLARE                                                     
    window INT;                                             
BEGIN                                                       
    FOREACH window IN ARRAY $1                              
    LOOP                                                    
        EXECUTE 'SELECT $1' USING window;                   
    END LOOP;                                               
$$ LANGUAGE plpgsql;                                        

SELECT test(ARRAY [30,60]);    

I expect that this code snippet would first print 30 and then 60. However, I get the following error.

psql:loop.sql:11: ERROR:  syntax error at end of input
LINE 7:         EXECUTE 'SELECT $1' USING window;
                                                ^
psql:loop.sql:13: ERROR:  function test(integer[]) does not exist
LINE 1: SELECT test(ARRAY [30,60]);
               ^
HINT:  No function matches the given name and argument types. You might need
 to add explicit type casts.

So the function definition has a syntax error, but I don't understand what the error is and how to fix it. I'd appreciate any help. Thanks!

1 Answer 1

9

Your function is declared as returns void so you can't return anything from it. If you want to return multiple values, you need to use returns setof integer

But it has more problems than that.

  1. you should give your parameter a name (not an error, but good coding style)
  2. to return a value from a function you need to use return. To return multiple values (because of returns setof) you need to use return next
  3. there is no need for a dynamic SQL to return a value, you can return the variable directly.
  4. Also not not an error, but: window is a keyword, I wouldn't use a variable with that name.

Applying all that, your function should look like this:

CREATE OR REPLACE FUNCTION test(p_input int[]) 
  RETURNS setof integer
as
$$  
DECLARE                                                     
  l_value INT;                                             
BEGIN                                                       
    FOREACH l_value IN ARRAY p_input                             
    LOOP                                                    
        return next l_value;
    END LOOP;                                               
end;
$$ 
LANGUAGE plpgsql;                                        

I am not sure if you are aware, but there is already a built-in function which achieves the same thing: unnest().

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for helping :) I need to get EXECUTE... USING to work as well. Do you know what's the issue with EXECUTE... USING in my code?
Update: it's because of the WINDOW keyword. It works after I changed the variable name.

Your Answer

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.