2017-02-15 19 views
2

Я пытаюсь перебрать несколько полей и запустить функцию на них:Перебор заданного списка значений в PL/PgSQL

FOR field IN ARRAY['f1','f2'] LOOP 
    execute pg_temp.converFieldToLower(newTableNameRaw,field) 
END LOOP; 

Это функция я пытаюсь использовать:

CREATE OR REPLACE FUNCTION pg_temp.converFieldToLower(t varchar, f varchar) RETURNS void AS $$ 
#variable_conflict use_variable 
BEGIN 
    EXECUTE concat_ws (' ', 'UPDATE',t,'SET',f,'= LOWER(',f,')'); 
END; 
$$ LANGUAGE plpgsql; 

Похоже, что это неправильный способ объявить массив, что я делаю неправильно?

ERROR: syntax error at or near "ARRAY" 
LINE 49:   FOR field IN ARRAY['f1','f2'] LOOP 
+0

Вы пишете * «поля» *, но демонстрируете * постоянные значения *. Итак: Константы, параметры или переменные plpgsql или поля таблицы? И является ли вход фактическим массивом? И хотите ли вы отказаться от любых результатов, например, продемонстрировать или присвоить результаты целям? Лучшее решение зависит от деталей вашей ситуации. Лучше всего предоставить полную (как можно более широкую) функцию plpgsql, показывающую задействованные типы данных, параметры функции и т. Д. –

+0

Я использую константные текстовые значения, как я демонстрирую. –

ответ

4

The FOREACH loop разработан специально для переборе элементов массива значения, например .:

FOREACH field IN ARRAY ARRAY['f1','f2'] LOOP 
    execute pg_temp.converFieldToLower(newTableNameRaw,field) into res; 
END LOOP; 

Функция был введен в Postgres 9.1.

0

Вы хотите unnest массив.

FOR field IN unnest(ARRAY['f1','f2']) LOOP 
    execute pg_temp.converFieldToLower(newTableNameRaw,field) 
END LOOP; 
+0

Это не должно работать - требуется 'FOR r IN SELECT unsest'. Он должен быть значительно медленнее, чем 'FOREACH' –

+0

' EXECUTE' не следует использовать здесь - см. @Erwin ответ –

2

Прежде всего, EXECUTE предназначен для динамического SQL и здесь нет ничего динамичного.
Вы, вероятно, собираетесь использовать PERFORM, чтобы отказаться от результатов.

Существует FOREACH для зацикливания, например @klin already provided. Подробнее:

Или вы можете просто использовать обычный SQL вместо этого, часто проще и быстрее:

PERFORM pg_temp.converFieldToLower(newTableNameRaw, t.val) 
FROM (VALUES ('f1'), ('f2')) t(val); -- for some given constants or variables 

Лучшее решение зависит от деталей ситуации. FOREACH может быть хорошей идеей для работы с реальными массивами.

Для двух или трех констант или переменных я бы просто изложил это и избегал любых накладных расходов. Проще, быстрее.

PERFORM pg_temp.converFieldToLower(newTableNameRaw, 'f1'); 
PERFORM pg_temp.converFieldToLower(newTableNameRaw, 'f2');