Respuesta
DO
espera un literal de cadena con código plpgsql. Los símbolos no se sustituyen dentro de las cadenas en psql.
Puede concatenar la cadena completa en una variable psql y luego ejecutarlo.
- ¿Cómo concatenar variables psql?
Un formato bastante multilínea no es posible porque (según la documentación):
Pero en cualquier caso, los argumentos de un meta-comando no pueden continuar más allá del final de la línea.
Ejemplo sencillo:
test=# \set value foo
test=# \set do 'BEGIN\n RAISE NOTICE ''v: %'', ' :'value' ';\nEND'
test=# DO :'do';
NOTICE: v: foo
Reemplace los saltos de línea con \n
(o elimínelos si no le gusta el formato bonito). Basado en este 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 ve así:
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
Agregué negrita énfasis a la variable para que sea más fácil de detectar.
Respuesta relacionada de @Pavel (ab) usando una variable de sesión del servidor:
- Hacer referencia a variables de sesión (\set var='value') de PL/PGSQL
Soluciones alternativas
Declaración preparada
Su solución actual no se ve tan mal. Yo simplificaría:
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$;
Mesa temporal
Solución similar con una tabla temporal:
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$;