PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Usa la variabile impostata dal meta-comando psql all'interno del blocco DO

Risposta

DO si aspetta un letterale stringa con codice plpgsql. I simboli non vengono sostituiti all'interno di stringhe in psql.
Potresti concatenare l'intera stringa in una variabile psql e quindi eseguilo.

  • Come concatenare le variabili psql?

Non è possibile un bel formato a più righe, perché (per documentazione):

Ma in ogni caso, gli argomenti di un meta-comando non possono continuare oltre la fine della linea.

Esempio semplice:

test=# \set value foo
test=# \set do 'BEGIN\n   RAISE NOTICE ''v: %'', ' :'value' ';\nEND'
test=# DO :'do';
NOTICE:  v: foo

Sostituisci le interruzioni di riga con \n (o rimuovili se non ti interessa un bel formato). Basato su questo codice adattato:

DO
'
DECLARE
   _val  text;
   _vals text[] := string_to_array(>>values<<, '','');
BEGIN
   FOREACH _val IN ARRAY _vals
   LOOP
     RAISE NOTICE ''v: %'', _val;
   END LOOP;
END
'

Si presenta così:

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

Ho aggiunto grassetto enfasi sulla variabile per renderla più facile da individuare.

Risposta correlata di @Pavel (ab)utilizzando una variabile di sessione del server:

  • Riferito a variabili di sessione (\set var='value') da PL/PGSQL

Soluzioni alternative

Dichiarazione preparata

La tua soluzione attuale non sembra così male. Semplificherei:

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

Tabella temporanea

Soluzione simile con una tabella temporanea:

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