sql >> Base de Datos >  >> RDS >> PostgreSQL

Use la variable establecida por el metacomando psql dentro del bloque DO

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$;