Resposta
DO
espera um string literal com código plpgsql. Símbolos não são substituídos dentro de strings no psql.Você pode concatenar a string inteira em uma variável psql e então execute.
- Como concatenar variáveis do psql?
O formato bonito de várias linhas não é possível, porque (por documentação):
Mas, de qualquer forma, os argumentos de um metacomando não podem continuar além do fim da linha.
Exemplo simples:
test=# \set value foo
test=# \set do 'BEGIN\n RAISE NOTICE ''v: %'', ' :'value' ';\nEND'
test=# DO :'do';
NOTICE: v: foo
Substitua as quebras de linha por
\n
(ou remova-os se você não se importa com o formato bonito). Com base neste código adaptado:DO
'
DECLARE
_val text;
_vals text[] := string_to_array(>>values<<, '','');
BEGIN
FOREACH _val IN ARRAY _vals
LOOP
RAISE NOTICE ''v: %'', _val;
END LOOP;
END
'
Se parece com isso:
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
Eu adicionei negrito ênfase na variável para torná-la mais fácil de identificar.
Resposta relacionada por @Pavel (ab) usando uma variável de sessão do servidor:
- Referindo-se a variáveis de sessão (\set var='value') de PL/PGSQL
Soluções alternativas
Declaração preparada
Sua solução atual não parece tão ruim. Eu simplificaria:
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$;
Tabela temporária
Solução semelhante com uma tabela temporária:
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$;