Синтаксическая ошибка PostgreSQL PL / pgSQL из-за цикла FOREACH

#postgresql #plpgsql

#postgresql #plpgsql

Вопрос:

Я пытаюсь изучить PL / pgSQL, написав несколько простых программ. Чтобы узнать о цикле FOREACH, я написал следующее:

 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]);    
  

Я ожидаю, что этот фрагмент кода будет сначала напечатан 30 , а затем 60 . Однако я получаю следующую ошибку.

 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.
  

Итак, в определении функции содержится синтаксическая ошибка, но я не понимаю, в чем ошибка и как ее исправить. Я был бы признателен за любую помощь. Спасибо!

Ответ №1:

Ваша функция объявлена как returns void , поэтому вы ничего не можете вернуть из нее. Если вы хотите вернуть несколько значений, вам нужно использовать returns setof integer

Но у него больше проблем, чем это.

  1. вы должны присвоить своему параметру имя (не ошибка, а хороший стиль кодирования)
  2. чтобы вернуть значение из функции, которую вам нужно использовать return . Чтобы вернуть несколько значений (из-за returns setof ), вам нужно использовать return next
  3. нет необходимости в динамическом SQL для возврата значения, вы можете вернуть переменную напрямую.
  4. Также не не ошибка, но: window это ключевое слово, я бы не использовал переменную с таким именем.

Применяя все это, ваша функция должна выглядеть следующим образом:

 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;                                        
  

Я не уверен, что вы в курсе, но уже есть встроенная функция, которая выполняет то же самое: unnest() .

Комментарии:

1. Спасибо за помощь 🙂 Мне тоже нужно приступить EXECUTE... USING к работе. Вы знаете, с EXECUTE... USING чем проблема в моем коде?

2. Обновление: это из-за WINDOW ключевого слова. Это работает после того, как я изменил имя переменной.