Отговор
DO
очаква низов литерал с plpgsql код. Символите не се заменят вътре в низовете в psql.
Можете да свържете целия низ в psql променлива и след това изпълнете го.
- Как да конкатенираме psql променливи?
Доста многоредов формат не е възможен, защото (по документация):
Но във всеки случай аргументите на метакоманда не могат да продължат отвъд края на реда.
Прост пример:
test=# \set value foo
test=# \set do 'BEGIN\n RAISE NOTICE ''v: %'', ' :'value' ';\nEND'
test=# DO :'do';
NOTICE: v: foo
Заменете прекъсванията на редове с \n
(или ги премахнете, ако не ви пука за красив формат). Въз основа на този адаптиран код:
DO
'
DECLARE
_val text;
_vals text[] := string_to_array(>>values<<, '','');
BEGIN
FOREACH _val IN ARRAY _vals
LOOP
RAISE NOTICE ''v: %'', _val;
END LOOP;
END
'
Изглежда така:
test=# \set do 'DECLARE\n _val text;\n _vals text[] := string_to_array(' :'values' ', '','');\nBEGIN\n FOREACH _val IN ARRAY _vals\n LOOP\n RAISE NOTICE ''v: %'', _val;\n END LOOP;\nEND'
test=# DO :'do';
NOTICE: v: foo
NOTICE: v: bar
NOTICE: v: baz
DO
Добавих удебелен наблегнете на променливата, за да я забележите по-лесно.
Свързан отговор от @Pavel (ab) с помощта на променлива на сесия на сървъра:
- Позоваване на променливи на сесията (\set var='value') от PL/PGSQL
Алтернативни решения
Подготвено изявление
Сегашното ви решение не изглежда толкова лошо. Бих опростил:
PREPARE get_values AS SELECT * FROM regexp_split_to_table(:'values', ',');
DO
$do$
DECLARE
_val text;
BEGIN
FOR _val IN EXECUTE
'EXECUTE get_values'
LOOP
RAISE NOTICE 'v: %', _val;
END LOOP;
END
$do$;
Временна таблица
Подобно решение с временна таблица:
CREATE TEMP TABLE tmp AS SELECT * FROM regexp_split_to_table(:'values', ',') v;
DO
$do$
DECLARE
_val text;
BEGIN
FOR _val IN
TABLE tmp
LOOP
RAISE NOTICE 'v: %', _val;
END LOOP;
END
$do$;